009-Joran配置框架
1. Joran配置
1.1.?Logback依賴Joran。Joran是個(gè)成熟、靈活和強(qiáng)大的配置框架。Logback模塊的許多能力都只能在Joran幫助下實(shí)現(xiàn)。
1.2. Joran實(shí)際上是個(gè)通用的配置系統(tǒng), 可以在記錄系統(tǒng)之外使用。
1.3. logback的設(shè)置可以在配置文件里指定, 用XML格式。Joran使用模式匹配規(guī)則處理XML文件, 對(duì)匹配了指定模式的內(nèi)容應(yīng)用規(guī)則(rule)。Rule類通常很小很專業(yè)。在Joran里, rule由一個(gè)pattern 和一個(gè)action組成。當(dāng)模式產(chǎn)生匹配時(shí), 就調(diào)用action。Patten與action的關(guān)系是Joran的核心。毫不夸張地說(shuō), 用簡(jiǎn)單的模式就能處理相當(dāng)復(fù)雜的需求, 精確匹配和通配符匹配可以進(jìn)行精確地處理。
2. SAX還是DOM?
2.1. 由于SAX API的基于事件的架構(gòu), 基于SAX的工具不能輕易地處理向前的引用, 即引用在當(dāng)前元素之后定義的元素。有循環(huán)引用的元素也是個(gè)問(wèn)題。更一般地說(shuō), DOM API允
許用戶在所有元素里進(jìn)行搜索和往前跳。
2.2. 這種額外的靈活性最初讓我們選擇了DOM API作為Joran的底層解析API。經(jīng)過(guò)一些試驗(yàn), 很快表明, 當(dāng)解釋規(guī)則是用pattern和action表達(dá)時(shí), 在解析DOM樹的過(guò)程中跳到
遠(yuǎn)處的元素沒(méi)有意義。Joran得到的元素只需要按照XML文件里連續(xù)的、深度優(yōu)先的順序。
2.3. Joran先是用DOM實(shí)現(xiàn), 然而, 作者換成了SAX, 以便得到只有SAX API才提供的元素位置信息。位置信息讓Joran能在錯(cuò)誤發(fā)生時(shí)顯示準(zhǔn)確的行號(hào)和列號(hào), 這對(duì)分析問(wèn)題非常
有用。
2.4. 由于其高度動(dòng)態(tài)的本性, Joran API沒(méi)有打算用于分析包含數(shù)以千計(jì)的元素的巨大的XML文檔。
3. 模式(Pattern)
3.1. Joran的模式本質(zhì)上是字符串。有兩種模式: 精確模式和通配符模式。
3.2. 模式"a/b"可以匹配嵌套在頂層元素<a>里的<b>元素, 不會(huì)匹配其他模式。這就是精確模式。
3.3. 通配符模式用來(lái)匹配前綴和后綴。例如, "*/a"模式匹配任何后綴是"a"的元素, 也就是XML文檔里的任意<a>元素, 而不是嵌套在<a>里的元素。"a/*"模式匹配任何前綴是
<a>的元素, 也就是嵌套在<a>里的任何元素。
4. 動(dòng)作(Action)
4.1. 動(dòng)作繼承Action類, 包含下面兩個(gè)抽象方法, 略去了其他方法。
?
4.2. 因此, 每個(gè)動(dòng)作必須實(shí)現(xiàn)begin()方法和end()方法。是否實(shí)現(xiàn)body()方法是可選的, 因?yàn)锳ction不提供任何操作。
5. RuleStore
5.1. 之前提到過(guò), 按照匹配的模式而調(diào)用動(dòng)作是Joran的一個(gè)核心概念。一個(gè)規(guī)則(rule)就是一個(gè)與模式的關(guān)聯(lián)關(guān)系加一個(gè)動(dòng)作。規(guī)則存放在RuleStore。
5.2. 上面說(shuō)過(guò), Joran構(gòu)建于SAX API之上。當(dāng)解析XML文檔時(shí), 每個(gè)元素的開始、體(body)和結(jié)束都產(chǎn)生對(duì)應(yīng)的事件。當(dāng)Joran配置器接收到這些事件時(shí), 就會(huì)在rule store里查找與當(dāng)前模式所對(duì)應(yīng)的動(dòng)作。例如, 對(duì)嵌套在頂級(jí)元素"A"里的B元素, 它的開始事件、體事件和結(jié)束事件的當(dāng)前模式是"A/B"。當(dāng)前模式是一種數(shù)據(jù)結(jié)構(gòu), 由Joran在接收和處理SAX事件時(shí)自動(dòng)維護(hù)。
5.3. 當(dāng)一些規(guī)則匹配了當(dāng)前模式時(shí), 精確匹配會(huì)覆蓋后綴匹配, 后綴匹配覆蓋前綴匹配。詳情請(qǐng)參考SimpleRuleStore類(ch.qos.logback.core.joran.spi.SimpleRuleStore)。
6. 解釋上下文(Interpretation context)
6.1. 為了讓多個(gè)動(dòng)作合作, begin()和end()方法的第一個(gè)參數(shù)是解釋上下文。解釋上下文包括一個(gè)對(duì)象堆棧、對(duì)象map、屬性列表和一個(gè)對(duì)調(diào)用了動(dòng)作的Joran解析器的引用。
7. HelloWorld例子
7.1. HelloWorld例子演示了使用Joran所需要的最基本的代碼。每當(dāng)HelloWorldAction的begin()方法被調(diào)用時(shí)就向控制臺(tái)打印"Hello World"。
7.2. XML文件的解析工作由一個(gè)配置器完成。我們開發(fā)了一個(gè)非常簡(jiǎn)單的配置器"SimpleConfigurator"。
7.3. HelloWorld程序把各部分組合到了一起:
創(chuàng)建包含規(guī)則的ruleMap和一個(gè)context;
把模式"helloWorld"與對(duì)應(yīng)的HelloWorldAction實(shí)例相關(guān)聯(lián), 從而創(chuàng)建一個(gè)解析規(guī)則;
創(chuàng)建一個(gè) SimpleConfigutator, 參數(shù)是前面的ruleMap;
調(diào)用配置器的doConfigure方法, 把指定的XML文件作為參數(shù);
最后一步, 打印context里的狀態(tài)消息;
7.4. helloWorld.xml文件包含一個(gè)<hello-world>元素, 沒(méi)有嵌套任何其他元素。
7.5. 新建一個(gè)名為JoranHelloWorld的Java工廠, 同時(shí)拷入相關(guān)jar包
7.6. 在工程李創(chuàng)建一個(gè)helloWorld.xml
7.7. 編寫SimpleConfigurator.java
package chapters.onJoran;import java.util.List; import java.util.Map; import ch.qos.logback.core.joran.GenericConfigurator; import ch.qos.logback.core.joran.action.Action; import ch.qos.logback.core.joran.action.ImplicitAction; import ch.qos.logback.core.joran.spi.ElementSelector; import ch.qos.logback.core.joran.spi.Interpreter; import ch.qos.logback.core.joran.spi.RuleStore;public class SimpleConfigurator extends GenericConfigurator {final Map<ElementSelector, Action> ruleMap;final List<ImplicitAction> iaList;public SimpleConfigurator(Map<ElementSelector, Action> ruleMap) {this(ruleMap, null);}public SimpleConfigurator(Map<ElementSelector, Action> ruleMap, List<ImplicitAction> iaList) {this.ruleMap = ruleMap;this.iaList = iaList;}@Overrideprotected void addInstanceRules(RuleStore rs) {for (ElementSelector elementSelector : ruleMap.keySet()) {Action action = ruleMap.get(elementSelector);rs.addRule(elementSelector, action);}}@Overrideprotected void addImplicitRules(Interpreter interpreter) {if (iaList == null) {return;}for (ImplicitAction ia : iaList) {interpreter.addImplicitAction(ia);}} }7.8. 編寫HelloWorldAction.java
package chapters.onJoran.helloWorld;import org.xml.sax.Attributes; import ch.qos.logback.core.joran.action.Action; import ch.qos.logback.core.joran.spi.InterpretationContext;public class HelloWorldAction extends Action {public void begin(InterpretationContext ec, String name, Attributes attributes) {System.out.println("Hello World");}public void end(InterpretationContext ec, String name) {} }7.9. 編寫HelloWorld.java
package chapters.onJoran.helloWorld;import java.util.HashMap; import java.util.Map; import ch.qos.logback.core.Context; import ch.qos.logback.core.ContextBase; import ch.qos.logback.core.joran.action.Action; import ch.qos.logback.core.joran.spi.ElementSelector; import ch.qos.logback.core.util.StatusPrinter; import chapters.onJoran.SimpleConfigurator;public class HelloWorld {public static void main(String[] args) throws Exception {Map<ElementSelector, Action> ruleMap = new HashMap<ElementSelector, Action>();// 把"helloWorld"模式和HelloWorldAction關(guān)聯(lián)ruleMap.put(new ElementSelector("helloWorld"), new HelloWorldAction());SimpleConfigurator simpleConfigurator = new SimpleConfigurator(ruleMap);// Joran內(nèi)部需要一個(gè)上下文Context context = new ContextBase();// 設(shè)置上下文simpleConfigurator.setContext(context);simpleConfigurator.doConfigure("helloWorld.xml");StatusPrinter.print(context);} }7.10. 運(yùn)行項(xiàng)目
8. 合作動(dòng)作(計(jì)算器例子)
8.1. 新建一個(gè)名為JoranCalculator的Java項(xiàng)目, 同時(shí)添加相關(guān)jar包
8.2. 文件calculator1.xml包擴(kuò)一個(gè)computation元素, 其中嵌套了一個(gè)literal元素, 內(nèi)容如下:
8.3. Calculator1.java
package chapters.onJoran.calculator1;import java.util.HashMap; import java.util.Map; import ch.qos.logback.core.Context; import ch.qos.logback.core.ContextBase; import ch.qos.logback.core.joran.action.Action; import ch.qos.logback.core.joran.spi.ElementSelector; import ch.qos.logback.core.util.StatusPrinter; import chapters.onJoran.SimpleConfigurator; import chapters.onJoran.calculator.action.ComputationAction1; import chapters.onJoran.calculator.action.LiteralAction;public class Calculator1 {public static void main(String[] args) throws Exception {Map<ElementSelector, Action> ruleMap = new HashMap<ElementSelector, Action>();ruleMap.put(new ElementSelector("computation"), new ComputationAction1());// 通配符模式, computation里的任何元素, 實(shí)際上我們的computation里面只有一個(gè)literal元素ruleMap.put(new ElementSelector("computation/*"), new LiteralAction());SimpleConfigurator simpleConfigurator = new SimpleConfigurator(ruleMap);Context context = new ContextBase();simpleConfigurator.setContext(context);simpleConfigurator.doConfigure("calculator1.xml");StatusPrinter.print(context);} }8.4. Calculator1.java程序里, 模式"computation"關(guān)聯(lián)于"ComputationAction1"實(shí)例, 所以調(diào)用ComputationAction1實(shí)例的begin()和end()方法。
package chapters.onJoran.calculator.action;import org.xml.sax.Attributes; import ch.qos.logback.core.joran.action.Action; import ch.qos.logback.core.joran.spi.InterpretationContext; import ch.qos.logback.core.util.OptionHelper;public class ComputationAction1 extends Action {public static final String NAME_ATR = "name";String nameStr;public void begin(InterpretationContext ec, String name, Attributes attributes) {nameStr = attributes.getValue(NAME_ATR);}public void end(InterpretationContext ec, String name) {if (OptionHelper.isEmpty(nameStr)) {} else {Integer i = (Integer) ec.peekObject();System.out.println("The computation named [" + nameStr + "] resulted in the value " + i);}} }8.5. Calculator1.java程序里, 模式"computation/*"關(guān)聯(lián)于"LiteralAction"實(shí)例, 所以調(diào)用LiteralAction實(shí)例的begin()方法, 用于把computation/literal的value屬性值添加至棧頂。
package chapters.onJoran.calculator.action;import org.xml.sax.Attributes; import ch.qos.logback.core.joran.action.Action; import ch.qos.logback.core.joran.spi.InterpretationContext; import ch.qos.logback.core.util.OptionHelper;public class LiteralAction extends Action {public static final String VALUE_ATR = "value";public void begin(InterpretationContext ic, String name, Attributes attributes) {String valueStr = attributes.getValue(VALUE_ATR);if (OptionHelper.isEmpty(valueStr)) {ic.addError("The literal action requires a value attribute");return;}try {// 往棧頂添加computation/literal的value屬性值Integer i = Integer.valueOf(valueStr);ic.pushObject(i);} catch (NumberFormatException nfe) {ic.addError("The value [" + valueStr + "] could not be converted to an Integer", nfe);throw nfe;}}public void end(InterpretationContext ic, String name) {} }8.6. SimpleConfigurator.java
package chapters.onJoran;import java.util.List; import java.util.Map; import ch.qos.logback.core.joran.GenericConfigurator; import ch.qos.logback.core.joran.action.Action; import ch.qos.logback.core.joran.action.ImplicitAction; import ch.qos.logback.core.joran.spi.ElementSelector; import ch.qos.logback.core.joran.spi.Interpreter; import ch.qos.logback.core.joran.spi.RuleStore;public class SimpleConfigurator extends GenericConfigurator {final Map<ElementSelector, Action> ruleMap;final List<ImplicitAction> iaList;public SimpleConfigurator(Map<ElementSelector, Action> ruleMap) {this(ruleMap, null);}public SimpleConfigurator(Map<ElementSelector, Action> ruleMap, List<ImplicitAction> iaList) {this.ruleMap = ruleMap;this.iaList = iaList;}@Overrideprotected void addInstanceRules(RuleStore rs) {for (ElementSelector elementSelector : ruleMap.keySet()) {Action action = ruleMap.get(elementSelector);rs.addRule(elementSelector, action);}}@Overrideprotected void addImplicitRules(Interpreter interpreter) {if (iaList == null) {return;}for (ImplicitAction ia : iaList) {interpreter.addImplicitAction(ia);}} }8.7. 運(yùn)行輸出computation/literal的value屬性值
8.8. 文件calculator2.xml除了computation和literal元素, add元素對(duì)literal的value屬性值作加法, multiply元素對(duì)literal的value屬性值作乘法:
8.9. Calculator2.java
package chapters.onJoran.calculator2;import java.util.HashMap; import java.util.Map; import ch.qos.logback.core.Context; import ch.qos.logback.core.ContextBase; import ch.qos.logback.core.joran.action.Action; import ch.qos.logback.core.joran.spi.ElementSelector; import ch.qos.logback.core.util.StatusPrinter; import chapters.onJoran.SimpleConfigurator; import chapters.onJoran.calculator.action.AddAction; import chapters.onJoran.calculator.action.ComputationAction2; import chapters.onJoran.calculator.action.LiteralAction; import chapters.onJoran.calculator.action.MultiplyAction;public class Calculator2 {public static void main(String[] args) throws Exception {Map<ElementSelector, Action> ruleMap = new HashMap<ElementSelector, Action>();ruleMap.put(new ElementSelector("*/computation"), new ComputationAction2());ruleMap.put(new ElementSelector("*/computation/literal"), new LiteralAction());ruleMap.put(new ElementSelector("*/computation/add"), new AddAction());ruleMap.put(new ElementSelector("*/computation/multiply"), new MultiplyAction());SimpleConfigurator simpleConfigurator = new SimpleConfigurator(ruleMap);Context context = new ContextBase();simpleConfigurator.setContext(context);simpleConfigurator.doConfigure("calculator2.xml");StatusPrinter.print(context);} }8.10. Calculator2.java程序里, 模式"*/computation/add"關(guān)聯(lián)于"AddAction"實(shí)例, 所以調(diào)用AddAction實(shí)例的begin()方法, 用于把棧頂?shù)?個(gè)數(shù)值作加法后把結(jié)果重新放入棧頂。
package chapters.onJoran.calculator.action;import java.util.EmptyStackException; import org.xml.sax.Attributes; import ch.qos.logback.core.joran.action.Action; import ch.qos.logback.core.joran.spi.InterpretationContext;public class AddAction extends Action {public void begin(InterpretationContext ic, String name, Attributes attributes) {int first = fetchInteger(ic);int second = fetchInteger(ic);ic.pushObject(first + second);}int fetchInteger(InterpretationContext ic) {int result = 0;try {Object o1 = ic.popObject();if (o1 instanceof Integer) {result = ((Integer) o1).intValue();} else {String errMsg = "Object [" + o1 + "] currently at the top of the stack is not an integer.";ic.addError(errMsg);throw new IllegalArgumentException(errMsg);}} catch (EmptyStackException ese) {ic.addError(("Expecting an integer on the execution stack."));throw ese;}return result;}public void end(InterpretationContext ic, String name) {} }8.11. Calculator2.java程序里, 模式"*/computation/multiply"關(guān)聯(lián)于"MultiplyAction"實(shí)例, 所以調(diào)用MultiplyAction實(shí)例的begin()方法, 用于把棧頂?shù)?個(gè)數(shù)值作乘法后把結(jié)果重新放入棧頂。
package chapters.onJoran.calculator.action;import org.xml.sax.Attributes; import ch.qos.logback.core.joran.action.Action; import ch.qos.logback.core.joran.spi.InterpretationContext; import java.util.EmptyStackException;public class MultiplyAction extends Action {public void begin(InterpretationContext ic, String name, Attributes attributes) {int first = fetchInteger(ic);int second = fetchInteger(ic);ic.pushObject(first * second);}int fetchInteger(InterpretationContext ic) {int result = 0;try {Object o1 = ic.popObject();if (o1 instanceof Integer) {result = ((Integer) o1).intValue();} else {String errMsg = "Object [" + o1 + "] currently at the top of the stack is not an integer.";ic.addError(errMsg);throw new IllegalArgumentException(errMsg);}} catch (EmptyStackException ese) {ic.addError("Expecting an integer on the execution stack.");throw ese;}return result;}public void end(InterpretationContext ic, String name) {} }8.12. ComputationAction2.java的作用是輸出計(jì)算結(jié)果
package chapters.onJoran.calculator.action;import java.util.Stack; import org.xml.sax.Attributes; import ch.qos.logback.core.joran.action.Action; import ch.qos.logback.core.joran.spi.InterpretationContext; import ch.qos.logback.core.util.OptionHelper;public class ComputationAction2 extends Action {public static final String NAME_ATR = "name";Stack<String> nameStrStack = new Stack<String>();public void begin(InterpretationContext ec, String name, Attributes attributes) {String nameStr = attributes.getValue(NAME_ATR);nameStrStack.push(nameStr);}public void end(InterpretationContext ec, String name) {String nameStr = (String) nameStrStack.pop();if (OptionHelper.isEmpty(nameStr)) {} else {Integer i = (Integer) ec.peekObject();System.out.println("The computation named [" + nameStr + "] resulted in the value " + i);}} }8.13. 運(yùn)行輸出計(jì)算結(jié)果
9. 隱式動(dòng)作(Implicit actions)
9.1. 到目前為止, 我們定義的規(guī)則都稱為顯式動(dòng)作, 因?yàn)閷?duì)當(dāng)前元素的模式/動(dòng)作關(guān)聯(lián)都能在rule store找到。然而, 在高度可擴(kuò)展的系統(tǒng)里, 組件的數(shù)量和類型都非常多, 因此為每個(gè)模式都關(guān)聯(lián)顯式動(dòng)作會(huì)非常冗長(zhǎng)乏味。
9.2. 同時(shí), 即使是在高度可擴(kuò)展的系統(tǒng)里, 仍然可以觀察到重復(fù)出現(xiàn)的規(guī)則。假設(shè)我們可以識(shí)別這些重復(fù)規(guī)則, 我們就可以處理在logback編譯期內(nèi)還是未知的包含子組件的組件。
9.3. Joran維持一個(gè)隱式動(dòng)作列表, 如果沒(méi)有顯式模式能匹配當(dāng)前模式時(shí), 就應(yīng)用隱式動(dòng)作。然而, 應(yīng)用隱式動(dòng)作并不總是適當(dāng)?shù)摹T趫?zhí)行隱式動(dòng)作前, Joran詢問(wèn)給定的隱式動(dòng)作是否適用于當(dāng)前情況。只有當(dāng)動(dòng)作回答"是"時(shí), Joran配置器才會(huì)調(diào)用隱式動(dòng)作。注意, 這個(gè)額外的步驟讓對(duì)給定的情況使用多個(gè)或零個(gè)動(dòng)作可能。
9.4. 新建一個(gè)名為JoranImplicit的Java項(xiàng)目, 同時(shí)添加相關(guān)jar包
9.5. 文檔implicit1.xml用于演示隱私動(dòng)作是如何工作的。
9.6. PrintMe程序?yàn)槟J?#34;*/foo"關(guān)聯(lián)了一個(gè)NOPAction動(dòng)作實(shí)例, 即所有名為"foo"的元素。如其名字所示, NOPAction的begin和end方法都為空。
package chapters.onJoran.implicit;import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import ch.qos.logback.core.Context; import ch.qos.logback.core.ContextBase; import ch.qos.logback.core.joran.action.Action; import ch.qos.logback.core.joran.action.ImplicitAction; import ch.qos.logback.core.joran.spi.ElementSelector; import ch.qos.logback.core.util.StatusPrinter; import chapters.onJoran.SimpleConfigurator;public class PrintMe {public static void main(String[] args) throws Exception {Map<ElementSelector, Action> ruleMap = new HashMap<ElementSelector, Action>();ruleMap.put(new ElementSelector("*/foo"), new NOPAction());List<ImplicitAction> iaList = new ArrayList<ImplicitAction>();iaList.add(new PrintMeImplicitAction());SimpleConfigurator simpleConfigurator = new SimpleConfigurator(ruleMap, iaList);Context context = new ContextBase();simpleConfigurator.setContext(context);simpleConfigurator.doConfigure("implicit1.xml");StatusPrinter.printInCaseOfErrorsOrWarnings(context);} }9.7. SimpleConfigurator.java
package chapters.onJoran;import java.util.List; import java.util.Map; import ch.qos.logback.core.joran.GenericConfigurator; import ch.qos.logback.core.joran.action.Action; import ch.qos.logback.core.joran.action.ImplicitAction; import ch.qos.logback.core.joran.spi.ElementSelector; import ch.qos.logback.core.joran.spi.Interpreter; import ch.qos.logback.core.joran.spi.RuleStore;public class SimpleConfigurator extends GenericConfigurator {final Map<ElementSelector, Action> ruleMap;final List<ImplicitAction> iaList;public SimpleConfigurator(Map<ElementSelector, Action> ruleMap) {this(ruleMap, null);}public SimpleConfigurator(Map<ElementSelector, Action> ruleMap, List<ImplicitAction> iaList) {this.ruleMap = ruleMap;this.iaList = iaList;}@Overrideprotected void addInstanceRules(RuleStore rs) {for (ElementSelector elementSelector : ruleMap.keySet()) {Action action = ruleMap.get(elementSelector);rs.addRule(elementSelector, action);}}@Overrideprotected void addImplicitRules(Interpreter interpreter) {if (iaList == null) {return;}for (ImplicitAction ia : iaList) {interpreter.addImplicitAction(ia);}} }9.8. PrintMe程序還在其隱式動(dòng)作列表里注冊(cè)了一個(gè)PrintMeImplicitAction動(dòng)作。PrintMeImplicitAction動(dòng)作適用于所有屬性"printme"為"true"的元素。PrintMeImplicitAction類繼承了ImplicitAction, isApplicable方法返回true, 才會(huì)調(diào)用動(dòng)作的begin()和end()方法。
package chapters.onJoran.implicit;import org.xml.sax.Attributes; import ch.qos.logback.core.joran.action.ImplicitAction; import ch.qos.logback.core.joran.spi.ElementPath; import ch.qos.logback.core.joran.spi.InterpretationContext;public class PrintMeImplicitAction extends ImplicitAction {public boolean isApplicable(ElementPath elementPath, Attributes attributes, InterpretationContext ec) {String printmeStr = attributes.getValue("printme");return Boolean.valueOf(printmeStr).booleanValue();}public void begin(InterpretationContext ec, String name, Attributes attributes) {System.out.println("Element [" + name + "] asked to be printed.");}public void end(InterpretationContext ec, String name) {} }9.9. NOPAction.java
package chapters.onJoran.implicit;import org.xml.sax.Attributes; import ch.qos.logback.core.joran.action.Action; import ch.qos.logback.core.joran.spi.InterpretationContext;/*** 不做任何操作*/ public class NOPAction extends Action {public void begin(InterpretationContext ec, String name, Attributes attributes) {}public void end(InterpretationContext ec, String name) {} }9.10. 對(duì)任何<foo>元素都不會(huì)調(diào)用PrintMeImplicitAction。對(duì)于其他元素, 由于沒(méi)有匹配任何顯式動(dòng)作, 所以調(diào)用PrintMeImplicitAction的isApplicable()方法。只有對(duì) 于那些包含屬性"printme"且其屬性值為"true"的元素, isApplicable()方法才返回"true"。<xyz />元素沒(méi)有可用的動(dòng)作, 所以會(huì)生成一個(gè)內(nèi)部錯(cuò)誤消息。這個(gè)錯(cuò)誤消息會(huì)被PrintMe程序的最后一條語(yǔ)句"StatusPrinter.print"打印出來(lái)。這就解釋了上面的輸出結(jié)果。
10. 動(dòng)態(tài)新規(guī)則
10.1. Joran的NewRuleAction動(dòng)作支持在解析XML文檔的過(guò)程中讓Joran配置器學(xué)習(xí)新規(guī)則。
10.2. 新建一個(gè)名為JoranNewRule的Java項(xiàng)目, 添加相關(guān)jar包
10.3. NewRuleCalculator程序使用了兩條規(guī)則, 一條規(guī)則處理最頂端的元素, 第二條規(guī)則學(xué)習(xí)新規(guī)則。
package chapters.onJoran.newRule;import java.util.HashMap; import java.util.Map; import ch.qos.logback.core.Context; import ch.qos.logback.core.ContextBase; import ch.qos.logback.core.joran.action.Action; import ch.qos.logback.core.joran.action.NewRuleAction; import ch.qos.logback.core.joran.spi.ElementSelector; import ch.qos.logback.core.util.StatusPrinter; import chapters.onJoran.SimpleConfigurator; import chapters.onJoran.calculator.ComputationAction2;public class NewRuleCalculator {public static void main(String[] args) throws Exception {Map<ElementSelector, Action> ruleMap = new HashMap<ElementSelector, Action>();ruleMap.put(new ElementSelector("*/computation"), new ComputationAction2());ruleMap.put(new ElementSelector("/computation/newRule"), new NewRuleAction());SimpleConfigurator simpleConfigurator = new SimpleConfigurator(ruleMap);Context context = new ContextBase();simpleConfigurator.setContext(context);simpleConfigurator.doConfigure("newRule.xml");StatusPrinter.printInCaseOfErrorsOrWarnings(context);} }10.4. NewRuleAction是logback-core的一部分, 工作原理與其他動(dòng)作基本相同, 有begin()和end()方法, 每當(dāng)解析器找到"new-rule"元素時(shí)被調(diào)用。當(dāng)被調(diào)用時(shí), begin()方法查找"pattern"和"actionClass"屬性, 然后實(shí)例化對(duì)應(yīng)的動(dòng)作類, 把模式/動(dòng)作的關(guān)聯(lián)關(guān)系作為一條新規(guī)則加入到Joran的rule store。下面是如何在xml文件里聲明新規(guī)則:
10.5. SimpleConfigurator.java、AddAction.java、ComputationAction2.java、LiteralAction.java和MultiplyAction.java根之前的例子一樣。
10.6. 運(yùn)行輸出
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的009-Joran配置框架的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 017_layout排版
- 下一篇: 010-映射诊断环境