缘起:
之前一段时间在复习以前学习的Digester使用的时候,由于机器上没有备份Digester的相关包,所以就直接去咱们apache的官网上找Digester的包,一般我都喜欢下最新版的jar包,虽然新版本有可能不稳定,但是迫于追求新东西的欲望,我一般会尝试下载最新jar包(当然最新的版本也可能是几年前发布的了)。所以理所当然就下载了Version: 3.3的Digester包。
惑起:
既然jar包下载完毕,就立马导入到项目中,期盼着红xx能够快点消失,可是等了一会却没有动静。如下代码的第二行是主要问题,其实我就是个Digester初学者而已,一时兴起来玩下,谁知玩出了火来,把以前的代码玩完了。
URL url = MyOldCode.class.getResource("rule.xml");
Digester digester = DigesterLoader.createDigester(url);
原因:
可能会用Digester的朋友见到上面的代码也许会感到陌生或者奇怪,说来也巧、也怪,偏偏我学的时候就是学得这种写法,看来下源代码,DigesterLoader.createDigester内部原本是这么写的:
public static Digester createDigester(URL rulesXml) {
RuleSet ruleSet = new FromXmlRuleSet(rulesXml);
Digester digester = new Digester();
digester.addRuleSet(ruleSet);
return digester;
}
可见这仅仅是封装了一点点‘繁琐’的代码而已,可是这代码在Digester3中消失不见了……(PS:并不是说以前的代码在Digester3中完全无法使用了,只是说部分少数有些变动了,如关于xml文件读取规则的有些改变了,其他我不怎么了解。)
新发现:
苦于对Digester使用的孤陋寡闻,而在网上搜索Digester3的使用无果(因为网上搜到的都是之前版本的使用),因此我只能硬着头皮去其官网上看那些外星文字了,一个个闪闪发亮的,好在现在科技发达了,有高科技能够为我们翻译了。一个个翻译下勉强了解个大概(别指望我翻译了,能讲个大概不错了,当然我也在努力中~)。
终于在http://commons.apache.org/digester/guide/binder.html这发现了Digester3的新特性了,在新版本中引入了RuleModule和RulesBinder。从名字可了解一个是规则模型,一个是规则捆绑者,似乎是用来代替老版本中的RuleSet的概念,当然在Digester3中是兼容RuleSet的大部分使用的。
使用对比:
Digester3之前的使用一般是这样的
try {
Digester digester = new Digester();
digester.addObjectCreate("emp", Emp.class);
digester.addSetProperties("emp");
digester.addBeanPropertySetter("emp/name");
digester.addBeanPropertySetter("emp/id");
Emp emp = (Emp) digester.parse(TestOld.class.getResource("emp.xml"));
System.out.println(emp);
} catch (IOException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
}
如果使用RuleSet的话,如下所示,即在RuleSet中添加规则,如果每次创建一个Digester都需要再次执行一遍
public class EmpRuleSet implements RuleSet {
//...略
@Override
public void addRuleInstances(Digester digester) {
digester.addObjectCreate("emp", Emp.class);
digester.addSetProperties("emp");
digester.addBeanPropertySetter("emp/name");
digester.addBeanPropertySetter("emp/id");
}
}
public static void main(String[] args) {
try {
Digester digester = new Digester();
EmpRuleSet ruleset = new EmpRuleSet();
ruleset.addRuleInstances(digester);
Emp emp = (Emp) digester.parse(TestOld.class.getResource("emp.xml"));
System.out.println(emp);
} catch (IOException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
}
}
而在Digester3中,提供了工厂的方式来创建Digester,即通过DigesterLoader来创建(DigesterLoader在老版本中似乎主要是用来加载xml规则文件用的),通过传入规则模型来生产Digester对象,使用如下,其中AbstractRulesModule是对RulesModule的封装,原本需要通过cinfigure传进的RulesBinder来设置规则,经过封装直接调用相应的方法就可以设置规则了。
public class EmpRuleModule extends AbstractRulesModule {
@Override
protected void configure() {
System.out.println("type");
//根据具体类创建对象
forPattern("emp").createObject().ofType(Emp.class);//.then().setProperties();//要一条龙的写法则通过then方法!
//设置标签上的全部对应属性
forPattern("emp").setProperties();
//将子节点set到其父节点
forPattern("emp/name").setBeanProperty();
forPattern("emp/id").setBeanProperty();
}
}
public class FirstTest {
public static void main(String[] args) {
try {
// 1、创建规则模型类,实现config方法来配置解析规则。然后new该实例来使用
EmpRuleModule empRuleModule = new EmpRuleModule();
// 2、根据规则模型类,创建解析器的工厂类
DigesterLoader loader = DigesterLoader.newLoader(empRuleModule);
// 3、通过工厂类创建解析器
Digester digester = loader.newDigester();// 同时调用了RuleModule的config方法添加规则
// 4、解析xml文件
Emp emp = digester.parse(FirstTest.class.getResource("emp.xml"));// 这里貌似用了泛型了,不需要转型了
System.out.println(emp);
Digester digester2 = loader.newDigester();// RuleModule的config不会再被调用了,只解析了一次
} catch (IOException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
}
}
}
其实该方式的底层还是用了RuleSet,只不过是只是存放了一份,而不是像之前那样每次都创建一份。
Over了吧,行吗?
写在结尾,My God,这文章真得好难写啊,毕竟对Digester内部实现不咋了解,写这个还主要是学习和记录下Digester3的使用,很多不足,请看者见谅。
噩梦结束了…… 拜