Digester解析XML文件

原文链接

TOMCAT底层解析server.xml使用。

 

Dom4j是把一个xml文件全部读取到内存中,构建成一个DOM树来解析,所以Dom4j适合读取比较小的xml文件。

SAX是基于文件流来解析xml文件的,在读取xml文件流时,SAX会通过节点来触发相应的操作,也可以说SAX是基于文件流的事情触发机制来解析xml文件的。

Digeter是apache的common项目,作用是将XML转化成对象,使用者直接从对象中获取xml的节点信息。Digester是对SAX的包装,它也是基于文件流来解析xml文件,只不过这些解析操作对用户是透明的。Tomcat的配置文件conf/server.xml就是用Digester来读取的。

 

    一般用来读取xml文件的工具包有DOM、SAX和JDOM等,但用过的人都知道,它们属于比较底层的API,写起来代码量很大,而且如果修改了xml文件的格式,代码也要做大幅度的改动。而使用Apache Jakarta的Digester,解析XML文件非常方便且不需要过多的关心底层的具体解析过程。Digester本来仅仅是Jakarta Struts中的一个工具,用于处理struts-config.xml配置文件。显然,将XML文件转换成相应的Java对象是一项很通用的功能,这个工具理应具有更广泛的用途,所以很快它就在Jakarta Commons项目(用于提供可重用的Java组件库)中有了一席之地。Digester由"事件"驱动,通过调用预定义的规则操作对象栈,将XML文件转换为Java对象。

 

    工作原理如下:

              Digester底层采用SAX(Simple API for XML)析XML文件,所以很自然的,对象转换由"事件"驱动,在遍历每个节点时,检查是否有匹配模式,如果有,则执行规则定义的操作,比如创建特定的Java对象,或调用特定对象的方法等。此处的XML元素根据匹配模式(matching pattern)识别,而相关操作由规则(rule)定义。

 

    如下xml代码,右边是左边元素对应的匹配模式:

Js代码   收藏代码
  1. <datasources>          'datasources'   
  2.   <datasource>         'datasources/datasource'   
  3.     <name/>            'datasources/datasource/name'   
  4.     <driver/>          'datasources/datasource/driver'    
  5.   </datasource>   
  6.   <datasource>         'datasources/datasource'   
  7.     <name/>            'datasources/datasource/name'   
  8.     <driver/>          'datasources/datasource/driver'    
  9.   </datasource>   
  10. </datasources>   

 

Tomcat与Digester的关系(注意该博客,很多资源)

Tomcat源码的catalina中利用Digester解析conf/server.xml

三个常见Digester例子

深入剖析Tomcat-Digester

理解Tomcat(一) 利用Digester解析xml文件

Digester处理多层的XML(仔细分析)

 

使用Digester解析XML配置文件

解析XML常用技术

 

 ==============================================================================

Xml代码   收藏代码
  1. <?xml version="1.0" encoding="UTF-8?>    
  2. <database>    
  3.     <user userName="guest" password="guest">    
  4.     </user>    
  5. </database>    

 1.addObjectCreate(String rule,Class class)

设置节点与Java对象的映射规则,rule指定节点的筛选规则,class设置映射对象。SAX解析时,遇到rule指定的节节点,会创建一个class实例放入堆栈中。

比如:digester.addObectCreate("database/user","com.model.UserBean").解析遇到user节点时,会创建一个UserBean实例并放入堆栈中。

 

2.addSetProperties(String rule)

设置节点的属性设置规则。当解析遇到符合rule的节点时,根据属性列表中的属性值对,使用Java反射机制使用标准的JavaBean方法设置栈顶对象实例;

比如:digester.addSetProperties("database/user"),解析遇到user节点时,会获取键值对 userName=guest,password=guest,获得栈顶的UserBean对象,设置实例的userName、password属性;

解析元素上的属性 

 

3.addBeanPropertySetter(String rule)

该方法的作用及使用方法类似于addSetProperties,只不过它是用rule所指定的标签来调用对象的setter。

该方法在tomcat6中貌似没有。 

tomcat6中Digester类路径为:import org.apache.tomcat.util.digester.Digester;

不为:import org.apache.commons.digester.Digester;

 

4.addSetNext(String rule,String methodName)

设置当前rule节点与父节点的调用规则,当遇到rule节点时,调用堆栈中的次栈顶元素调用methodName方法。将栈顶元素作为次顶元素指定方法的输入参数。

比如:digester.addSetNext("database/user","addUser"),调用database实例的addUser,user为参数

 

5.addCallMethod(String rule,String methodName,int paraNumber)

该方法同样设置对象的属性,但更加灵活,不需要对象具有setter

根据rule规则指定的属性,调用对象的methodName方法,paraNumber参数是表示方法需要的参数个数,当paraNumber=0时,可以单独使用,不然需要配合addCallParam方法

比如:digester.addCallMethod("database/user/uerName","setUserName",0);

 

6.addCallParam(String rule,int paraIndex,String attributeName)

该方法与addCallMethod配合使用,根据rule指定的标签属性来调用方法

paraIndex表明需要填充的方法形参序号,从0开始,方法由addCallMethdo指定,attributeName指定标签属性名;

 

使用注意事项:

   1.Digester类调用的顺序,必须与XML数据文件绝对一致;

   2.Digester类依赖于JavaBean规范,类必须符合规范;

   3.XML文件中标签/属性的名称必须与Bean中的一致(包括大小写);

 

 ==================================================================

 关键方法说明

(1)    serverDigester.addObjectCreate("Server","com.test.server.digester.Server")

当解析xml文件时,遇到“Server”就初始化一个“com.test.server.digester.Server”对象,并且把该对象压入栈顶

(2)    serverDigester.addSetProperties("Server", "port", "port")

给Server对象注册port属性,当解析到Server节点的port属性时调用Server的setPort方法

(3)    serverDigester.addSetNext("Server/Listener", "addListener","com.test.server.digester.Listener")

当解析Server节点下的Listener节点的时候,调用Server对象的addListener方法,把当前Listener对象写入到Server对象中。无论Server节点下有多少个Listener节点,都会调用addListener方法

(4)    serverDigester.addCallMethod("Server/Service/Engine", "setEngine", 0)

Service中添加Engine,调用当前top object的setEngine函数,参数个数为0

addCallMethod与addBeanPropertySetter方法等价

 

Example1:

Xml代码   收藏代码
  1. <?xml version="1.0" encoding="ISO-8859-1"?>  
  2. <student name="llin" age="16" grade="3">  
  3.     <subject name="math" teacher="yu" />  
  4. </student>  

 

Java代码   收藏代码
  1. package digester;  
  2.   
  3. import java.util.ArrayList;  
  4.   
  5. public class Student {  
  6.     private String name;  
  7.     private int age;  
  8.     private int grade;  
  9.     private ArrayList<Subject> list = new ArrayList();  
  10.       
  11.     public Student (){  
  12.         System.out.println("A student go to school");  
  13.     }  
  14.   
  15.     public void add ( Subject subjects ){  
  16.         System.out.println("add Subjects " + subjects.getName() + " to the Student: "this.getName());  
  17.         list.add( subjects );  
  18.     }        
  19.     /  
  20.     public int getAge() {  
  21.         return age;  
  22.     }  
  23.   
  24.     public void setAge(int age) {  
  25.         System.out.println( " set age of Student:" + name);  
  26.         this.age = age;  
  27.     }  
  28.   
  29.     public int getGrade() {  
  30.         return grade;  
  31.     }  
  32.   
  33.     public void setGrade(int grade) {  
  34.         System.out.println( " set score of Student:" + name );  
  35.         this.grade = grade;  
  36.     }  
  37.   
  38.     public String getName() {  
  39.         return name;  
  40.     }  
  41.   
  42.     public void setName(String name) {  
  43.         System.out.println(" set name pf Student" );  
  44.         this.name = name;  
  45.     }  
  46.   
  47.     public ArrayList<Subject> getList (){  
  48.         return this.list;  
  49.     }  
  50. }  

 

Java代码   收藏代码
  1. package digester;  
  2.   
  3. public class Subject {  
  4.     private String name;  
  5.     private String teacher;  
  6.   
  7.     public Subject() {  
  8.         System.out.println("One subjects waiting scheduling!");  
  9.     }  
  10.   
  11.     public void print() {  
  12.         System.out.println("Subjects  :" + name + "of " + teacher + "in schedule");  
  13.     }      
  14.     /      
  15.     public String getName() {  
  16.         return name;  
  17.     }  
  18.   
  19.     public void setName(String name) {  
  20.         System.out.println(" set name of Subjects:" + name);  
  21.         this.name = name;  
  22.     }  
  23.   
  24.     public String getTeacher() {  
  25.         return teacher;  
  26.     }  
  27.   
  28.     public void setTeacher(String teacher) {  
  29.         System.out.println(" set teacher of Subjects :" + teacher);  
  30.         this.teacher = teacher;  
  31.     }     
  32. }  

 

 

Java代码   收藏代码
  1. package digester;  
  2. import java.io.File;  
  3. import java.io.IOException;  
  4. import java.util.Iterator;  
  5. import org.apache.tomcat.util.digester.Digester;  
  6. import org.xml.sax.SAXException;  
  7.   
  8. public class StudentDigesterTest {  
  9.     public static void main ( String [] args ) throws IOException{  
  10.         unUseRule();  
  11.         //useRule();  
  12.     }     
  13.       
  14.     public static void unUseRule(){  
  15.         File xml = new File( "../apache-tomcat-6.0.41-src/test/student.xml");  
  16.         Digester digester = new Digester();  
  17.           
  18.         digester.addObjectCreate( "student" , "digester.Student" );  
  19.         digester.addSetProperties("student");  
  20.         digester.addObjectCreate("student/subject" , "digester.Subject");  
  21.         digester.addSetProperties("student/subject");  
  22.         //上面该句可用这句代替digester.addSetProperties("student/subject","subject","subject");  
  23. /** 
  24. * public void addSetProperties(String pattern,String attributeName,String propertyName) 
  25. */  
  26.         digester.addSetNext("student/subject" , "add" );  
  27.           
  28.         Student student = null;  
  29.         try {  
  30.             student = (Student)digester.parse(xml);  
  31.         }catch ( SAXException e ){  
  32.             System.out.println("parse with mistakes!");  
  33.         } catch (IOException e) {  
  34.             e.printStackTrace();  
  35.         }  
  36.         Iterator it = student.getList().iterator();  
  37.         while ( it.hasNext()) {  
  38.   
  39.         }  
  40.     }  
  41.       
  42.     public static void useRule(){  
  43.         File xml = new File( "../apache-tomcat-6.0.41-src/test/student.xml");  
  44.         Digester digester = new Digester();  
  45.         digester.addRuleSet(new MyRuleSet());  
  46.           
  47.         Student student = null;  
  48.         try {  
  49.             student = (Student)digester.parse(xml);  
  50.         }catch ( SAXException e ){  
  51.             System.out.println("parse with mistakes!");  
  52.         } catch (IOException e) {  
  53.             e.printStackTrace();  
  54.         }  
  55.         Iterator it = student.getList().iterator();  
  56.         while ( it.hasNext()) {  
  57.   
  58.         }  
  59.     }  
  60. }  

  

Java代码   收藏代码
  1. package digester;  
  2.   
  3. import org.apache.tomcat.util.digester.Digester;  
  4. import org.apache.tomcat.util.digester.RuleSetBase;  
  5.   
  6. public class MyRuleSet  extends RuleSetBase{  
  7.     @Override  
  8.     public void addRuleInstances(Digester digester) {  
  9.         digester.addObjectCreate( "student" , "digester.Student" );  
  10.         digester.addSetProperties("student");  
  11.         digester.addObjectCreate("student/subject" , "digester.Subject");  
  12.         digester.addSetProperties("student/subject");  
  13.         digester.addSetNext("student/subject" , "add" );  
  14.     }  
  15. }  

 

 两种方法结果都为:


 

 Example2:

viewcache2.xml:

Xml代码   收藏代码
  1. <?xml version="1.0" encoding="UTF-8" ?>    
  2. <viewcache>    
  3.     <areas>    
  4.         <area id="1098" parentId="1001" areaType="province" name="上海" ordering="1867" phoneArea="111"/>   
  5.         <area id="1099" parentId="1098" areaType="capital" name="北京" ordering="1868" phoneArea="010"/>  
  6.     </areas>    
  7. </viewcache>   

 

Java代码   收藏代码
  1. package digester;  
  2. import java.util.ArrayList;  
  3. import java.util.List;  
  4.   
  5. public class ViewCache {    
  6.     private ArrayList<Area> areaList             = new ArrayList<Area>();    
  7.   
  8.       
  9.     public ArrayList getAreaList() {  
  10.         return areaList;  
  11.     }  
  12.   
  13.   
  14.     public void setAreaList(ArrayList areaList) {  
  15.         this.areaList = areaList;  
  16.     }  
  17.   
  18.   
  19.     // 供Digester调用的方法    
  20.     public void addArea(Area area) {    
  21.         System.out.println("addArea..");  
  22.         this.areaList.add(area);    
  23.     }    
  24. }    

 

Java代码   收藏代码
  1. package digester;  
  2.   
  3. public class Area {    
  4.     private int    id;    
  5.     private String name;    
  6.     private String areaType;    
  7.     private int    parentId;    
  8.     private int    ordering;    
  9. //    private String zip;    
  10.         
  11.     private String phoneArea;  
  12.   
  13.     public Area(){  
  14.         System.out.println("Area constructor..");  
  15.     }  
  16.       
  17.     public int getId() {  
  18.         return id;  
  19.     }  
  20.   
  21.     public void setId(int id) {  
  22.         System.out.println( " set id of Area:" + id);  
  23.         this.id = id;  
  24.     }  
  25.   
  26.     public String getName() {  
  27.         return name;  
  28.     }  
  29.   
  30.     public void setName(String name) {  
  31.         System.out.println( " set name of Area:" + name);  
  32.         this.name = name;  
  33.     }  
  34.   
  35.     public String getAreaType() {  
  36.         return areaType;  
  37.     }  
  38.   
  39.     public void setAreaType(String areaType) {  
  40.         System.out.println( " set areaType of Area:" + areaType);  
  41.         this.areaType = areaType;  
  42.     }  
  43.   
  44.     public int getParentId() {  
  45.         return parentId;  
  46.     }  
  47.   
  48.     public void setParentId(int parentId) {  
  49.         System.out.println( " set parentId of Area:" + parentId);  
  50.         this.parentId = parentId;  
  51.     }  
  52.   
  53.     public int getOrdering() {  
  54.         return ordering;  
  55.     }  
  56.   
  57.     public void setOrdering(int ordering) {  
  58.         System.out.println( " set ordering of Area:" + ordering);  
  59.         this.ordering = ordering;  
  60.     }  
  61.   
  62.     /*public String getZip() { 
  63.         return zip; 
  64.     } 
  65.  
  66.     public void setZip(String zip) { 
  67.         this.zip = zip; 
  68.     }*/  
  69.   
  70.     public String getPhoneArea() {  
  71.         return phoneArea;  
  72.     }  
  73.   
  74.     public void setPhoneArea(String phoneArea) {  
  75.         System.out.println( " set phoneArea of Area:" + phoneArea);  
  76.         this.phoneArea = phoneArea;  
  77.     }    
  78.       
  79.       
  80. }  

 

Java代码   收藏代码
  1. package digester;  
  2. import java.io.IOException;  
  3.   
  4. import org.apache.tomcat.util.digester.Digester;  
  5. import org.xml.sax.SAXException;  
  6.   
  7. public class AreaDigester {    
  8.         
  9.     public ViewCache digester() throws Exception {    
  10.         Digester digester = new Digester();    
  11.         digester.setValidating(false);    
  12.         digester.addObjectCreate("viewcache/areas", ViewCache.class);    
  13.         // 指明匹配模式和要创建的类     
  14.         digester.addObjectCreate("viewcache/areas/area", Area.class);    
  15.           
  16.         //使用这句可以打印出Area字段set值时的syso语句,下面的打印不出,没搞清楚。。。  
  17.         digester.addSetProperties("viewcache/areas/area");    
  18.          
  19. //        digester.addSetProperties("viewcache/areas/area/id");    
  20. //        digester.addSetProperties("viewcache/areas/area/parentId", "parentId", "parentId");    
  21. //        digester.addSetProperties("viewcache/areas/area/name", "name", "name");    
  22. //        digester.addSetProperties("viewcache/areas/area/areaType", "areaType", "areaType");    
  23. //        digester.addSetProperties("viewcache/areas/area/ordering", "ordering", "ordering");    
  24. //        //digester.addSetProperties("viewcache/areas/area/zip", "zip", "zip");    
  25. //        digester.addSetProperties("viewcache/areas/area/phoneArea", "phoneArea", "phoneArea");    
  26.   
  27.         // 当移动到下一个标签中时的动作    
  28.         digester.addSetNext("viewcache/areas/area""addArea");    
  29.             
  30.         ViewCache vc = null;    
  31.         try {    
  32.             vc = (ViewCache) digester.parse("../apache-tomcat-6.0.41-src/test/viewcache2.xml");    
  33.         } catch (IOException e) {    
  34.             throw new Exception(e);    
  35.         } catch (SAXException e) {    
  36.             throw new Exception(e);    
  37.         }    
  38.         return vc;    
  39.     }    
  40.       
  41.     public static void main(String[] args) {  
  42.         AreaDigester m = new AreaDigester();  
  43.         ViewCache vc = null;  
  44.         try {  
  45.             vc = m.digester();  
  46.         } catch (Exception e) {  
  47.             // TODO Auto-generated catch block  
  48.             e.printStackTrace();  
  49.         }  
  50.     }  
  51. }    

 结果:



 -----------------------------------------------------------------------------------------

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值