缘起:

之前一段时间在复习以前学习的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的使用,很多不足,请看者见谅。

噩梦结束了…… 拜