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代码,右边是左边元素对应的匹配模式:
<datasources> 'datasources' <datasource> 'datasources/datasource' <name/> 'datasources/datasource/name' <driver/> 'datasources/datasource/driver' </datasource> <datasource> 'datasources/datasource' <name/> 'datasources/datasource/name' <driver/> 'datasources/datasource/driver' </datasource> </datasources>
Tomcat与Digester的关系(注意该博客,很多资源)
Tomcat源码的catalina中利用Digester解析conf/server.xml
Digester处理多层的XML(仔细分析)
==============================================================================
<?xml version="1.0" encoding="UTF-8?> <database> <user userName="guest" password="guest"> </user> </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 version="1.0" encoding="ISO-8859-1"?> <student name="llin" age="16" grade="3"> <subject name="math" teacher="yu" /> </student>
package digester; import java.util.ArrayList; public class Student { private String name; private int age; private int grade; private ArrayList<Subject> list = new ArrayList(); public Student (){ System.out.println("A student go to school"); } public void add ( Subject subjects ){ System.out.println("add Subjects " + subjects.getName() + " to the Student: "+ this.getName()); list.add( subjects ); } ///////////////////////////////////////////////// public int getAge() { return age; } public void setAge(int age) { System.out.println( " set age of Student:" + name); this.age = age; } public int getGrade() { return grade; } public void setGrade(int grade) { System.out.println( " set score of Student:" + name ); this.grade = grade; } public String getName() { return name; } public void setName(String name) { System.out.println(" set name pf Student" ); this.name = name; } public ArrayList<Subject> getList (){ return this.list; } }
package digester; public class Subject { private String name; private String teacher; public Subject() { System.out.println("One subjects waiting scheduling!"); } public void print() { System.out.println("Subjects :" + name + "of " + teacher + "in schedule"); } ///////////////////////////////////////////////////// public String getName() { return name; } public void setName(String name) { System.out.println(" set name of Subjects:" + name); this.name = name; } public String getTeacher() { return teacher; } public void setTeacher(String teacher) { System.out.println(" set teacher of Subjects :" + teacher); this.teacher = teacher; } }
package digester; import java.io.File; import java.io.IOException; import java.util.Iterator; import org.apache.tomcat.util.digester.Digester; import org.xml.sax.SAXException; public class StudentDigesterTest { public static void main ( String [] args ) throws IOException{ unUseRule(); //useRule(); } public static void unUseRule(){ File xml = new File( "../apache-tomcat-6.0.41-src/test/student.xml"); Digester digester = new Digester(); digester.addObjectCreate( "student" , "digester.Student" ); digester.addSetProperties("student"); digester.addObjectCreate("student/subject" , "digester.Subject"); digester.addSetProperties("student/subject"); //上面该句可用这句代替digester.addSetProperties("student/subject","subject","subject"); /** * public void addSetProperties(String pattern,String attributeName,String propertyName) */ digester.addSetNext("student/subject" , "add" ); Student student = null; try { student = (Student)digester.parse(xml); }catch ( SAXException e ){ System.out.println("parse with mistakes!"); } catch (IOException e) { e.printStackTrace(); } Iterator it = student.getList().iterator(); while ( it.hasNext()) { } } public static void useRule(){ File xml = new File( "../apache-tomcat-6.0.41-src/test/student.xml"); Digester digester = new Digester(); digester.addRuleSet(new MyRuleSet()); Student student = null; try { student = (Student)digester.parse(xml); }catch ( SAXException e ){ System.out.println("parse with mistakes!"); } catch (IOException e) { e.printStackTrace(); } Iterator it = student.getList().iterator(); while ( it.hasNext()) { } } }
package digester; import org.apache.tomcat.util.digester.Digester; import org.apache.tomcat.util.digester.RuleSetBase; public class MyRuleSet extends RuleSetBase{ @Override public void addRuleInstances(Digester digester) { digester.addObjectCreate( "student" , "digester.Student" ); digester.addSetProperties("student"); digester.addObjectCreate("student/subject" , "digester.Subject"); digester.addSetProperties("student/subject"); digester.addSetNext("student/subject" , "add" ); } }
两种方法结果都为:
Example2:
viewcache2.xml:
<?xml version="1.0" encoding="UTF-8" ?> <viewcache> <areas> <area id="1098" parentId="1001" areaType="province" name="上海" ordering="1867" phoneArea="111"/> <area id="1099" parentId="1098" areaType="capital" name="北京" ordering="1868" phoneArea="010"/> </areas> </viewcache>
package digester; import java.util.ArrayList; import java.util.List; public class ViewCache { private ArrayList<Area> areaList = new ArrayList<Area>(); public ArrayList getAreaList() { return areaList; } public void setAreaList(ArrayList areaList) { this.areaList = areaList; } // 供Digester调用的方法 public void addArea(Area area) { System.out.println("addArea.."); this.areaList.add(area); } }
package digester; public class Area { private int id; private String name; private String areaType; private int parentId; private int ordering; // private String zip; private String phoneArea; public Area(){ System.out.println("Area constructor.."); } public int getId() { return id; } public void setId(int id) { System.out.println( " set id of Area:" + id); this.id = id; } public String getName() { return name; } public void setName(String name) { System.out.println( " set name of Area:" + name); this.name = name; } public String getAreaType() { return areaType; } public void setAreaType(String areaType) { System.out.println( " set areaType of Area:" + areaType); this.areaType = areaType; } public int getParentId() { return parentId; } public void setParentId(int parentId) { System.out.println( " set parentId of Area:" + parentId); this.parentId = parentId; } public int getOrdering() { return ordering; } public void setOrdering(int ordering) { System.out.println( " set ordering of Area:" + ordering); this.ordering = ordering; } /*public String getZip() { return zip; } public void setZip(String zip) { this.zip = zip; }*/ public String getPhoneArea() { return phoneArea; } public void setPhoneArea(String phoneArea) { System.out.println( " set phoneArea of Area:" + phoneArea); this.phoneArea = phoneArea; } }
package digester; import java.io.IOException; import org.apache.tomcat.util.digester.Digester; import org.xml.sax.SAXException; public class AreaDigester { public ViewCache digester() throws Exception { Digester digester = new Digester(); digester.setValidating(false); digester.addObjectCreate("viewcache/areas", ViewCache.class); // 指明匹配模式和要创建的类 digester.addObjectCreate("viewcache/areas/area", Area.class); //使用这句可以打印出Area字段set值时的syso语句,下面的打印不出,没搞清楚。。。 digester.addSetProperties("viewcache/areas/area"); // digester.addSetProperties("viewcache/areas/area/id"); // digester.addSetProperties("viewcache/areas/area/parentId", "parentId", "parentId"); // digester.addSetProperties("viewcache/areas/area/name", "name", "name"); // digester.addSetProperties("viewcache/areas/area/areaType", "areaType", "areaType"); // digester.addSetProperties("viewcache/areas/area/ordering", "ordering", "ordering"); // //digester.addSetProperties("viewcache/areas/area/zip", "zip", "zip"); // digester.addSetProperties("viewcache/areas/area/phoneArea", "phoneArea", "phoneArea"); // 当移动到下一个标签中时的动作 digester.addSetNext("viewcache/areas/area", "addArea"); ViewCache vc = null; try { vc = (ViewCache) digester.parse("../apache-tomcat-6.0.41-src/test/viewcache2.xml"); } catch (IOException e) { throw new Exception(e); } catch (SAXException e) { throw new Exception(e); } return vc; } public static void main(String[] args) { AreaDigester m = new AreaDigester(); ViewCache vc = null; try { vc = m.digester(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
结果:
相关推荐
4. **解析XML文件**:使用Digester解析XML文件,并根据定义的规则创建Java对象。 #### 五、总结 通过上述介绍可以看出,Digester是一个非常有用的工具,它可以大大简化XML解析的过程。在实际开发中,尤其是处理...
标题“利用commons-digester解析XML”涉及到的是Java开发中的一种处理XML文档的工具——Apache Commons Digester。这个库提供了一种方便的方式来映射XML文档结构到Java对象,从而简化了XML数据的处理过程。 Apache ...
这个"digester解析XML文件实例"是一个很好的学习资源,帮助开发者理解如何在实际项目中运用Digester。 首先,我们要了解Digester的基本工作原理。Digester通过定义一系列规则(Rules),当解析到XML文档中特定的...
3. **解析 XML**:创建好 Digester 实例后,使用 `parse` 方法读取 XML 文件并执行预定义的规则。代码示例如下: ```java Digester digester = new Digester(); digester.setValidating(false); // 关闭验证,...
3. **解析XML**:使用 Digester 的 `parse()` 方法读取XML文件,根据预先定义的规则进行处理。 4. **结果处理**:最后,Digester会生成一个对象模型,代表了XML文档的内容。 以下是一个简单的 Digester 使用示例: ...
要使用Digester解析XML文档,首先需要创建一个 `org.apache.commons.digester.Digester` 类的实例,并配置必要的模式和规则,最后调用 `parse()` 方法。 以下是一个简单的示例代码: ```java import org.apache....
5. **解析XML**:最后,使用配置好的 Digester 对象解析XML文件: ```java Root root = null; try (InputStream is = new FileInputStream("path_to_xml_file.xml")) { root = digester.parse(is); } catch ...
这个“digester解析xml必备包.rar”包含了三个关键的jar包,它们是实现Digester功能所必需的。 1. **commons-logging-1.2.jar**:这是Apache Commons Logging库的版本1.2。它提供了一个抽象层,允许开发者使用多种...
这个“org.apache.commons.digester解析XML.rar”压缩包包含了一个测试工程,它演示了如何使用Digester库来解析XML文件并映射到Java对象上。下面将详细介绍这个库的功能、使用方法以及在实际开发中的应用。 1. **...
在示例代码中, DigesterDriver演示了如何配置 Digester来解析XML文件,创建`Catalog`对象并填充其`Book`和`Magazine`子对象,以及相关的`Article`对象。每个元素的属性通过`addBeanPropertySetter()`设置,而对象...
在Java开发中,Struts框架提供了一个强大的工具——Digester,用于解析XML文件并自动创建、配置Java对象。本文将详细介绍如何使用Digester处理具有嵌套结构的XML文档,并通过一个具体的实例——"DigesterXmlTest"来...
本篇文章将详细介绍如何使用`Digester`解析XML,以及在使用过程中需要的依赖库。 首先,`Digester`的核心功能是通过定义规则来将XML元素与Java对象的属性或方法关联,这样在解析XML时,可以自动创建和填充Java对象...
《digester解析XML详解》 在Java开发中,XML作为一种数据交换格式,广泛应用于配置文件、数据传输等场景。为了方便地将XML文档解析为Java对象,Apache组织提供了一个名为Digester的工具库,它允许开发者通过规则来...
Java中的Digester库是Apache Commons项目的一部分,它提供了一种方便的方式来解析XML文档,并将解析结果映射到Java对象模型上。这个库特别适合于创建简单的XML到Java对象的映射,而不需要编写大量的手动解析代码。在...
**使用Digester解析XML并验证** 1. **设置 Digester 规则** 在使用Digester之前,我们需要定义一系列规则,告诉Digester在遇到XML文档的哪些元素时执行什么操作。这些规则通常涉及到创建新对象、设置对象属性或者...
本文将深入探讨如何通过接口和Digester类来解析XML文件,创建并填充Java对象。 首先,理解 Digester 类的工作原理是至关重要的。Digester 是一个规则驱动的XML解析器,它通过匹配XML文档中的模式(Pattern),执行...