Tomcat中xml的解析器Digester 第二篇(共三篇)

为了方便这篇文章仍然使用第一篇的XML和Bean。 第一篇实现了SaxCatalogUnmarshaller, 利用SAX技术将XML转成一个装配好的Java Object. 但是其中有很多需要改进的地方。 最明显需要改进的就是有大量的if-else来匹配刚读进来的XML元素, 如果XML中大量不同的类对应, 将会有更多的if-else而且不可重用。 对于大量if-else, 策略模式是一个很好的选择。

apache 的 Digester正是利用了策略模式来解决这个问题, 当SAX产生startElement, endElement等事件的时候, 马上将事件分配给匹配的Rule。 客户端只需要注册不同的模式和它们的对应关系,剩下来的事情转发给各不同的Rule实现。
[img]http://alanwu.iteye.com/topics/download/e4dc9828-e503-45f7-818b-210ce708fffa[/img]

Digester最开始使用的是Struts, 使用后发现非常好且通用. Digester被提到commons.apache.org.


apache Digester中 实现的Rule:ObjectCreateRule.begin代码:
[code]
/**
* Process the beginning of this element.
*
* @param attributes The attribute list of this element
*/
public void begin(Attributes attributes) throws Exception {
// 识别类名
// Identify the name of the class to instantiate
String realClassName = className;
if (attributeName != null) {
String value = attributes.getValue(attributeName);
if (value != null) {
realClassName = value;
}
}
if (digester.log.isDebugEnabled()) {
digester.log.debug("[ObjectCreateRule]{" + digester.match +
"}New " + realClassName);
}
// 实现类并将实例放到堆栈中
// Instantiate the new object and push it on the context stack
Class clazz = digester.getClassLoader().loadClass(realClassName);
Object instance = clazz.newInstance();
digester.push(instance);

}
[/code]

end代码

[code]
/**
* Process the end of this element.
*/
public void end() throws Exception {

Object top = digester.pop();
if (digester.log.isDebugEnabled()) {
digester.log.debug("[ObjectCreateRule]{" + digester.match +
"} Pop " + top.getClass().getName());
}

}
[/code]

上面start和end代码, 和SaxCatalogUnmarshaller比较可以看出, 对XML元素的对比,类实现和对内容堆栈的处理都封装出来了,客户端无需关注这些技术细节。

客户端只需要将不同的模式和不同的Rule对应的注册到Digester里,分发和实现就可以交给Digester和不同的Rule做了。

DigesterDriver.java:

[code]
package benewu.gmail.study.tomcat.digester;

import java.io.File;
import java.net.URL;

import org.apache.commons.digester.Digester;



public class DigesterDriver {

public static void main( String[] args ) {

try {
Digester digester = new Digester();
digester.setValidating( false );

//The patterns must match XML elements, based on their name and location in the document tree.
//The syntax used to describe the matching patterns resembles the XPath match patterns, a little:
//the pattern catalog matches the top-level <catalog> element,
//the pattern catalog/book matches a <book> element nested directly inside a <catalog> element

/*ObjectCreateRule: 利用默认构造函数创建类实例并且压到堆栈,
*元素结束的时候会从堆栈pop出来.
*/
digester.addObjectCreate( "catalog", Catalog.class );
digester.addObjectCreate( "catalog/book", Book.class );

/*
* BeanPropertySetterRule: 将名字属性赋值给栈顶的元素
* (Example: <page>10</page>.)
*/
digester.addBeanPropertySetter( "catalog/book/author", "author" );
digester.addBeanPropertySetter( "catalog/book/title", "title" );

/*
* SetNextRule: pop栈顶实例并且利用定义的方法传递给下个对象实例, 通常用来将一个完整的bean插到父对象上.
*/
digester.addSetNext( "catalog/book", "addBook" );

digester.addObjectCreate( "catalog/magazine", Magazine.class );
digester.addBeanPropertySetter( "catalog/magazine/name", "name" );

digester.addObjectCreate( "catalog/magazine/article", Article.class );

/*
* SetPropertiesRule: 将名字属性的值赋给栈顶对象.
* (Typically used to handle XML constructs like <article page="10">.)
*/
digester.addSetProperties( "catalog/magazine/article", "page", "page" );
digester.addBeanPropertySetter( "catalog/magazine/article/headline" );
digester.addSetNext( "catalog/magazine/article", "addArticle" );

digester.addSetNext( "catalog/magazine", "addMagazine" );

URL fileURL = DigesterDriver.class.getResource("catalog.xml");
File input = new File(fileURL.getFile());
Catalog c = (Catalog)digester.parse( input );

System.out.println( c.toString() );

} catch( Exception exc ) {
exc.printStackTrace();
}
}
}
[/code]

DigesterDriver 实现了和SaxCatalogUnmarshaller完全相同的功能, 但更加灵活和可扩展。

这里使用的Rule有:
ObjectCreateRule, SetPropertiesRule, BeanPropertySetterRule, SetNextRule, 在代码中已经做了注释。


下节我将分析Tomcat中使用到和自己实现的部分Rule, 和典型应用。


参考:
1 The Hidden Gems of Jakarta Commons
http://www.onjava.com/pub/a/onjava/2004/12/22/jakarta-gems-1.html?page=2

2 Parsing, indexing, and searching XML with Digester and Lucene
http://www.ibm.com/developerworks/java/library/j-lucene/

3 Learning and Using Jakarta Digester
http://www.onjava.com/pub/a/onjava/2002/10/23/digester.html?page=1
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值