Tomcat与Digester的关系
我们利用Tomcat做服务器开发Web应用时,总会有一个配置文件web.xml,进行一些对象的实例化或是Servlet的映射的配置,所以要想理解Tomcat的一些配置问题,首先需要了解Tomcat是如何利用xml文件来进行配置的?答案就是利用开源的Digest进行XML的解析,然后构建响应的容器或者完成其他的配置,这些我会在单篇文章中具体深入讲解,作为这个专题的第一个部分,就首先避重就轻地讲解一下Digester这个开源的xml解析工具
Digester
org.apache.commons.digester
该包提供了基于规则的,可任意处理XML文档的类
org.apache.commons.digester.Digester是Digester类库的主类,该类可用于解析XML文档。
- 解析过程分为两步:
- 定义好模式(定义要匹配的标签)
- 将模式与规则(定义匹配到标签后的行为的对象)相关联
- 模式与规则
- 模式:
模式由如下形式的字符串拼接而成:
父元素的模式+”/”+子元素的模式 - 规则:
一条规则指明了当Digester对象匹配到了指定的模式时触发的一个或多个动作。
- 规则是org.apache.commons.digester.Rule类的实例
- Rule类有begin()方法和end()方法。在解析XML文档时,
- 当Digester实例匹配到某个模式的开始标签时,它会相应地调用Rule的begin()方法
- 当Digester实例匹配到某个模式的结束标签时,它会相应地调用Rule的end()方法
- 模式:
Digester库已经预定义了一些规则。可以直接使用这些规则而无须深入理解Rule类的实现
规则一:创建对象
在遇到指定模式时创建对象可以调用addObjectCreate()方法- 通过模式和创建对象的类进行调用
public void addObjectCreate( String pattern , Class class ) public void addObjectCreate( String pattern , String className)
- 可以在XML中通过属性指定类进行实例化的重载
public void addObjectCreate( String pattern , String className , String attributeName ) public void addObjectCreate(String pattern , String attributeName , Class class )
- addObjectCreate()方法创建的对象会被压入一个内部栈中,Digester库负责维护这个内部栈
- 规则二:设置属性
public void addSetProperties( String pattern )
利用pattern匹配到的标签内的属性设置实例的属性,一般紧跟addObjectCreate使用,如:
<Student age="12" height="1.8"/>
就可以在生成实例后,利用age和height属性初始化对象student中的同名属性
- 规则三:调用方法
Digester类允许添加一条规则,若模式得到匹配,可以调用内部栈顶部的对象的某个方法
public void addCallMethod(String pattern , String methodName )
- 规则四:创建对象之间的关系
- 我们之前有提过,Digester实例有一个内部栈,用于存储临时的对象。当使用addObjectCreate()方法实例化一个类时,会把结果压入这个栈中。
- 当调用了两次addObjectCreate()方法时,会有两个对象被放入栈中,这时候调用addSetNext()方法会调用第一个放入栈中的对象的方法,并将第二个对象作为参数,设置第一个对象和第二个对象的关系。
public void addSetNext ( String pattern , String methodName )
例讲Digester类的使用
首先呢,为了能够正常使用Digester,我们需要下载它运行所需要的类结构:
如果登陆了CSDN账号的话,可以在如下的链接下载,由我免费提供^_^
commons-digester.jar
commons-collections.jar
commons-logging.jar
commons-beanutils.jar
- 环境配置好了,我们应该构造情景,我们的情景就是解析xml中学生和课程对象的初始化,xml文件如下:
<?xml version="1.0" encoding="ISO-8859-1"?>
<student name="llin" age="16" grade="3">
<subjects name="math" teacher="yu" />
</student>
- 创建我们需要实例化的两个对象的类
import java.util.ArrayList;
/**
* Created by liulin on 16-5-1.
*/
public class Student {
private String name;
private int age;
private int grade;
private ArrayList<Subjects> list = new ArrayList();
public Student (){
System.out.println("A student go to school");
}
public void add ( Subjects 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<Subjects> getList (){
return this.list;
}
}
/**
* Created by liulin on 16-5-1.
*/
public class Subjects {
private String name;
private String teacher;
public Subjects() {
System.out.println("One subjects waiting scheduling!");
}
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;
}
public void print() {
System.out.println("Subjects :" + name + "of " + teacher + "in schedule");
}
}
- 最后就是我们利用Digester进行解析的代码了
import org.apache.commons.digester.Digester;
import org.xml.sax.SAXException;
import java.io.*;
import java.util.ArrayList;
import java.util.Iterator;
/**
* Created by liulin on 16-5-1.
*/
public class DigesterTest {
public static void main ( String [] args ) throws IOException{
File xml = new File( "/home/liulin/byj/test.xml");
Digester digester = new Digester();
digester.addObjectCreate( "student" , "Student" );
digester.addSetProperties("student");
digester.addObjectCreate("student/subjects" , "Subjects");
digester.addSetProperties("student/subjects");
digester.addSetNext("student/subjects" , "add" );
Student student = null;
try {
student = (Student)digester.parse(xml);
}catch ( SAXException e ){
System.out.println("parse with mistakes!");
}
Iterator it = student.getList().iterator();
while ( it.hasNext()) {
}
}
}
- 测试的结果如下:
Rule
我们可以通过自己实现Rule类构造一个自己的Rule规则(覆写begin()和end()方法),但是大多数的情况下,都没有这个必要….
可以通过如下方法添加规则:
public void addRule( String pattern , Rule rule )
RuleSet
我们可以通过继承RuleSetBase构造自己的RuleSet,这个是很实用的
因为我们可以将一大串的规则封装成一个单一的规则,更方便使用,屏蔽了更多的细节
import org.apache.commons.digester.Digester;
import org.apache.commons.digester.RuleSetBase;
/**
* Created by liulin on 16-5-1.
*/
public class RuleSet extends RuleSetBase{
@Override
public void addRuleInstances(Digester digester) {
digester.addObjectCreate( "student" , "Student" );
digester.addSetProperties("student");
digester.addObjectCreate("student/subjects" , "Subjects");
digester.addSetProperties("student/subjects");
digester.addSetNext("student/subjects" , "add" );
}
}
然后我们看我们的主体代码,更加简洁易懂了
import org.apache.commons.digester.Digester;
import org.xml.sax.SAXException;
import java.io.*;
import java.util.ArrayList;
import java.util.Iterator;
/**
* Created by liulin on 16-5-1.
*/
public class DigesterTest {
public static void main ( String [] args ) throws IOException{
File xml = new File( "/home/liulin/byj/test.xml");
Digester digester = new Digester();
digester.addRuleSet( new RuleSet ());
Student student = null;
try {
student = (Student)digester.parse(xml);
}catch ( SAXException e ){
System.out.println("parse with mistakes!");
}
Iterator it = student.getList().iterator();
while ( it.hasNext()) {
}
}
}