最近看看tomcat的源码实现,发现将xml解析为java对象使用了 Digester;故而学习一下;
Digester 通过递归的思想解决xml的解析;使用Stack 的堆栈结构,xml解析的时候,主要关注 begin(开始一个标签) 和 end(结束一个标签) 事件;
begin:创建对象并入栈;
end:对象出栈;
在begin 和 end 之间,我们可以设置对象(栈顶)属性,并将栈顶的下一个对象与当前栈顶对象建立父子关系(一对一或一对多;与xml中父子节点定义一致);
xml节点的匹配使用pattern ,支持模糊匹配; (节点之间使用/分割)
事件 使用预先定义的Rule;
具体请看下例:
<system>
<ams attr="attr-A" attrKey="propertyRule" attrValue="propertyRuleValue"> <name>供应商管理</name> </ams> <dmc realClass="Dmc_B"> <name>数据中心</name> </dmc></system>解析以上的xml 并转为 System 的对象
定义如下的类:
<system> 对应的类
public class System {
private Ams ams;private Dmc dmc;
public Ams getAms() {
return ams; }public void setAms(Ams ams) {
this.ams = ams; }public Dmc getDmc() {
return dmc; }public void setDmc(Dmc dmc) {
this.dmc = dmc; }@Override
public String toString() { return "System [ams=" + ams + ", dmc=" + dmc + "]"; }}<ams> 对应的类
public class Ams {
private System system; public void setSystem(System system) { this.system = system; }private String name;
private String attr; private String propertyRule;public void setPropertyRule(String propertyRule) {
this.propertyRule = propertyRule; }public String getName() {
return name; }public void setName(String name) {
this.name = name; }public void setAttr(String attr) {
this.attr = attr; }@Override
public String toString() { return "Ams [system=" + (null==system?null:system.hashCode()) + ", name=" + name + ", attr=" + attr + ", propertyRule=" + propertyRule + "]"; }}
<dmc> 对应的类 有三个 abstract 的Dmc、继承Dmc 的 Dmc_A、Dmc_B
public abstract class Dmc {
private String name;public Dmc(String name) {
super(); this.name = name; }public String getName() {
return name; }public void setName(String name) {
this.name = name; }@Override
public String toString() { return "Dmc [name=" + name + "]"; }}public class Dmc_A extends Dmc {
public Dmc_A(String name) {
super(name); }@Override
public String toString() { return "Dmc_A [getName()=" + getName() + "]"; }}
public class Dmc_B extends Dmc{
public Dmc_B(String name) {
super(name); }@Override
public String toString() { return "Dmc_B [getName()=" + getName() + "]"; }}自定义的DmcObjectCreationFactory
public class DmcObjectCreationFactory extends AbstractObjectCreationFactory<Dmc> {
@Override
public Dmc createObject(Attributes attributes) throws Exception { String realClass = attributes.getValue("realClass"); if("Dmc_A".equals(realClass)) { return new Dmc_A("默认名称"); } else if("Dmc_B".equals(realClass)) { return new Dmc_B("默认名称"); } return null; }}
测试类
public class DigesterTest {
public static void main(String[] args) throws IOException, SAXException { Rule ruleA = new ObjectCreateRule(com.hym.digester.bean.System.class); Rule ruleB = new ObjectCreateRule(com.hym.digester.bean.Ams.class); Rule ruleC = new SetNextRule("setAms", com.hym.digester.bean.Ams.class); Rule ruleF = new SetTopRule("setSystem", com.hym.digester.bean.System.class); Rule ruleD = new SetPropertiesRule(); Rule ruleE = new SetPropertyRule("attrKey", "attrValue"); Rule ruleG = new FactoryCreateRule(DmcObjectCreationFactory.class); Rule ruleH = new SetNextRule("setDmc", com.hym.digester.bean.Dmc.class); Digester digester = new Digester(); digester.addRule("system", ruleA); digester.addRule("system/ams", ruleB); digester.addRule("system/ams", ruleC); digester.addRule("system/ams", ruleD); digester.addRule("system/ams", ruleE); digester.addRule("system/ams", ruleF); digester.addRule("system/dmc", ruleG); digester.addRule("system/dmc", ruleH); Object obj = digester.parse(new File("D:/WorkSpace/LearnDemo/src/resource/digester/System.xml")); System.out.println(obj); }}