XML已经成为应用程序开发过程中不可或缺的技术,在Java EE开发中,一种常见的应用就是把全局JavaBean对象的属性和JavaBean对象之间的关联关系用XML文档来配置,例如,很多开源项目(例如,Strtus、hibernate、spring等框架)都是用XML文档作为配置文件来提供系统中的一些全局JavaBean对象的初始化信息。只需要修改XML文档中的相应信息,不需要修改Java源程序和重新编译源程序。要实现这种功能,应用程序在初始化时需要根据XML文档中的信息来生成相关的JavaBean对象,可以直接使用DOM和SAX等XML解析工具先解析出XML文档中的信息,然后再根据这些信息组装出相关的JavaBean对象和JavaBean对象之间的关联关系,但这种做法涉及了太多的细节问题,过于复杂和繁琐。为此Apache组织推出了Commons Digester框架,Commons Digester框架是一套XML to Object的API,专门用于将XML文档转换为相关的JavaBean对象,它让开发人员不用编写XML文档和组装JavaBean对象的具体代码与细节。
Digester中有俩大概念:匹配模式(matching pattern)和规则(rule)。
匹配模式是以字符串的形式存在,以上面的xml为例,students/student , students/student/name 就是俩个匹配模式。其实每个匹配模式就是一个路径,说明该匹配模式指代的是哪个元素,如students/student 指代的就是元素<student>,students/student/name指代的就是元素<name>.
而规则(rule)则是一系列动作。在Digester中规则是一个抽象类(org.apache.commons.digester.Rule). 其中包括四个方法begin()、body()、end()、finish(),可以看出这四个方法都是时点方法,按照时间顺序执行。目前在Rule中这四个方法都是空方法,需要它的实现者去重写。
Digester提供了一些内置规则(rule),使用这些内置规则就可完全的将xml文档转为Java bean了,而不必在定义了。以下五类九个rule较为常用(为了方便,这个是我直接从百度百科上弄下来的):
A:对象创建
1.ObjectCreateRule 当begin()方法被调用时, 此rule创建相应Java对象, 并将其push到Digester的对象栈上。当end()方法被调用时, 栈顶对象将被pop, Digester内所有对该对象的引用都将失效。
2.FactoryCreateRule 创建Java对象的另一种选择。当待创建的Java对象没有无参构造函数,或需要在创建时需要进行额外的设置时,需要用此rule。
B:属性设置
3.SetPropertiesRule 当begin()方法被调用时, Digester使用标准的Java反射API,将栈顶对象的属性设置为XML元素的同名属性值。
4.SetPropertyRule 当begin()方法被调用时, Digester调用栈顶对象某指定属性的设置方法,设置其值。
C:父子关系管理
5.SetNextRule 当end()方法被调用时, Digester将栈顶元素设置进次栈顶元素中(调用相应的设置方法)。
6.SetTopRule 当end()方法被调用时, Digester将次栈顶元素设置进栈顶元素中(调用相应的设置方法)。
D:任意方法调用
7.CallMethodRule 当end()方法被调用时, Digester将调用栈顶元素指定名称的方法。除了方法名外,此rule还需要配置参数数目,参数类型。参数值一般通过CallParamRule得到。
8.CallParamRule 此rule内嵌于CallParamRule中,按顺序(相对于0)定义了CallParamRule中参数值的来源,可选的来源包括当前XML元素的属性或内容。
Digester类结构图
由于Digester只是对SAX更高层次上的一个封装,所以也不会脱离”事件”驱动的。具体过程:
当Digester利用SAX解析到XML文件中的某个元素时,通过“事件”驱动调用Digester相应方法(由于Digester继承了 DefaultHandler,那么实际就会调用Digeser的startElement()、characters()、 endElement()),在startElement()方法中,Digester首先会生成该元素的匹配模式(如:当前处理到student节点 那么匹配模式就是students/student),然后根据这个匹配模式去找到该匹配模式下事先绑定的所有规则(rule),依次调用这些规则 rule的begin()方法。之后会通过事件调用characters()方法(取得元素值)、最后调用endElement()方法,在此方法中会先后调用规则的body()、end()方法,从而完成解析xml的。在此过程中如何生成xml元素对应的java bean、以及怎样生成、生成后的java bean如何管理,就需要通过规则Rule及规则间的相互配合来完成了。