How tomcat works 读书笔记十五 Digester库(一)

2015-01-25 11:43:17 · 作者: · 浏览: 26
Digester库

在前面的几个章节里,我们对tomcat里各个组件的配置完全是使用写硬编码的形式完成的。

Context context = new StandardContext();
Loader loader = new WebappLoader();
context.setLoader(loader);
就完成了向context容器里添加WepappLoader的功能。
这么做的问题就在于,一旦我想更改配置就必须得重新加载Bootstrap类。
幸运的是tomcat的设计者使用了一种给我灵活的配置方式,即使用xml来记录tomcat里各个组件的配置情况。并且使用Digester将xml中的元素转化为java对象。

Digester是Apache软件基金会Jakarta项目下的一个开源项目。更多具体的信息请问百度。
这里我们主要介绍Digester能干什么。
在apaceh官网上对这个项目的描述如下
XML-to- Java-object mapping utility.
看到了吧,就是咱们在上面说的把xml里面的元素转化为java类。

Digester类

先看一个xml 如下
  

  
  
    
    
在这个xml里面,根元素是employee,里面包含一个元素office,office里面又包含一个元素address。
在讨论Digester如何解析xml前,我们先说两个概念,模式与规则。
模式:我无法给出一个书面的关于模式的定义。粗略的说在上面的xml中,employee元素的模式是employee;office元素的模式是employee/office;以此类推address元素的模式就是employee/office/address。大家应该大概明白了吧。说白了模式就是路径。
规则:是org.apache.commons.digester.Rule类的实例。规则指定了在分析xml时遇到某一规则应该执行的动作。说的够清楚了吧。另外Rule还有begin与end方法。挡在解析到匹配某个模式的元素的开始标签时会指向begin方法,end还用说吗?
例如在解析上面的xml时:
1 先解析到了employee元素,此时查找是否有对应的规则与此模式即employee匹配,若有,执行Rule对象的begin方法
2 遇到了office元素,此时查找是否有对应的规则与此模式即employee/office匹配,若有,执行Rule对象的begin方法
3 遇到了address元素的开始标签,此时查找是否有对应的规则与此模式即employee/office/address匹配,若有,执行Rule对象的begin方法
4 遇到address元素的结束标签,调用想匹配规则对象的end方法。
5 6自己补全,我不写了。


Digester预定义的规则

Digester预定义的规则主要有以下几个。

创建对象

创建对象一共有四种方式
最主要的两个例子如下:
digester.addObjectCreate("employee",ex15.pyrmont.digestertest.Employee.class);
或者
digester.addObjectCreate("employee","ex15.pyrmont.digestertest.Employee");
第一个参数是模式名,第二个参数可以是类名(String类型),也可以使Class。
还有两种方式就是在xml中写明要加载的类。
若xml中如下
className="ex15.pyrmont.digestertest.Employee">
代码写成下面的样子
digester.addObjectCreate("employee","ex15.pyrmont.digestertest.Employee", "className");

employee是类名,程序会按照上面方法的第三个参数去employee元素里找对应的属性值作为要加载的类,当然如果找不到那个属性的话,就是有上面方法的第二个参数来加载。同样第二个参数可以使String类型的类名也可以使Class。

(employee,office,address都在文章的最后)


设置属性

digester.addSetProperties("employee");
上面这句代码做的事情就是: 系统找到匹配employee模式的元素后,如果那个元素有属性,就将相应的属性值注入到类里面去。

如果xml中如上,里面在它所匹配的那个类里面就至少得有setFirstName,setLastName两个方法。

调用方法

digester.addCallMethod("employee", "printName");
上面代码的功能就是找到匹配employee模式的元素后(准确的说是遇到结束标签后),就调用最先创建的那个类的printName方法。

创建对象之间的联系

digester.addSetNext("employee/office", "addOffice");
第一个参数的模式应该是这种形式的
firstobject/secondobjcet
上面的代码的意思就是调用firstobject的addOffice方法,并且以secondobject为参数。当然这两个object前面都已经产生好了。

下面这个例子让大家熟悉一下Digester的用法
示例代码1
package ex15.pyrmont.digestertest;

import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import org.apache.commons.digester.Digester;

public class Test02 {

  public static void main(String[] args) {
    String path = System.getProperty("user.dir") + File.separator +
            "src"+File.separator  + "etc";
    File file = new File(path, "employee2.xml");
    Digester digester = new Digester();
    // add rules
    digester.addObjectCreate("employee", "ex15.pyrmont.digestertest.Employee");
    digester.addSetProperties("employee");    
    digester.addCallMethod("employee", "printName");
    
    digester.addObjectCreate("employee/office", "ex15.pyrmont.digestertest.Office");
    digester.addSetProperties("employee/office");
 
    digester.addSetNext("employee/office", "addOffice");
 
    digester.addObjectC