您的位置:首页 > 运维架构 > Apache

Apache开源项目之2[Digester的使用]

2011-02-17 17:42 337 查看
之前的工作经常用到struts1框架,但是说实话,里面的具体实现确实不甚清楚,于是乎今天在看ActionServlet初始化资源的时候整理了一下Digester的使用。要系统的理解Digester可能还得在SAX上费些时间。我这里只是把几个简单的应用罗列一下,希望对自己和别人都有所帮助。

 

Digester是基于SAX之上的一种简化XML解析逻辑的一个开源项目,来源于 Strut1的项目。

Digester在处理xml文件的时候主要分成以下几步:

 

实例化一个Digester实例,为digester添加一些属性(如nameSpace,validate等),接着是为digester添加rule规则,最后将目标xml文件转换为InputStream给digester解析。

 

Digester中各种各样的rule是Digester之所以如此灵活运用的根本。

 

在介绍解析的例子之前还有一点需要声明,Digester在解析对象是是利用栈(Stack)原理来处理方法的作用对象的。

 

接着我们从2个例子来介绍,2中典型的解析XML的方法(前一种是针对InnerText类型的XML,后一种是针对property格式的XML)。

 

先来看第一种解析:

ServletBean.java

public class ServletBean {
private String servletName;
private String servletClass;
private Map<String, String> paramMap;
public Map<String, String> getParamMap() {
return paramMap;
}
public String getServletClass() {
return servletClass;
}
public void setServletClass(String servletClass) {
this.servletClass = servletClass;
}
public String getServletName() {
return servletName;
}
public void setServletName(String servletName) {
this.servletName = servletName;
}
public void setParamInfo(String name, String value) {
if (paramMap == null) {
paramMap = new HashMap<String, String>();
}
paramMap.put(name, value);
}
}


 

test1.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app>
<servlet>
<servlet-name>testServlet</servlet-name>
<servlet-class>digester.TestServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/test.xml</param-value>
</init-param>
<init-param>
<param-name>convertNull</param-name>
<param-value>yes</param-value>
</init-param>
</servlet>
</web-app>


 

处理方法:

public void digester1() throws Exception{
InputStream is = this.getClass().getResourceAsStream("test1.xml");

Digester digester = new Digester();

digester.addObjectCreate("web-app/servlet", "digester.ServletBean");
digester.addCallMethod("web-app/servlet/servlet-name", "setServletName", 0);
digester.addCallMethod("web-app/servlet/servlet-class", "setServletClass", 0);
digester.addCallMethod("web-app/servlet/init-param", "setParamInfo", 2);
digester.addCallParam("web-app/servlet/init-param/param-name", 0);
digester.addCallParam("web-app/servlet/init-param/param-value", 1);

ServletBean servletBean = (ServletBean)digester.parse(is);

System.out.println(servletBean.getParamMap());
}


 

根据最后的处理方法我们来做一番分析:

1.当碰到pattern为web-app/servlet时候,创建一个ServletBean实例压如栈中。

2.当碰到pattern为web-app/servlet-name的时候,寻找当前占类引用(ServletBean引用)的setServletName方法,该方法参数个数为0.

3.当碰到pattern为web-app/servlet/init-param的时候,寻找当前栈引用并调用其方法setParamInfo该方法有2个参数。

4.将符合web-app/servlet/init-param/param-name的pattern元素内容作为第0个参数设置到setParamInfo方法中。

5.最后将xml文件以InputStream的形式送给digester解析。处理完毕后返回栈顶类的引用(ServletBean),进而可以获得当中的内容。

 

 

 

再来看第2种解析:

Foo.java

public class Foo {
private String name;
private List<Bar> barList = new ArrayList<Bar>();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void addBar(Bar bar) {
barList.add(bar);
}
public List<Bar> getBarList() {
return barList;
}
}


 

Bar.java

public class Bar {
private String id;
private String title;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}


 

test2.xml

<?xml version="1.0" encoding="UTF-8"?>
<foo name="The Parent">
<bar id="123" title="The First Child" />
<bar id="456" title="The Second Child" />
</foo>


 

处理方法:

InputStream is = this.getClass().getResourceAsStream("test2.xml");

Digester digester = new Digester();

digester.addObjectCreate("foo", "digester.Foo");
digester.addSetProperties("foo");
digester.addObjectCreate("foo/bar", "digester.Bar");
digester.addSetProperties("foo/bar");
digester.addSetNext("foo/bar", "addBar", "digester.Bar");

Foo foo = (Foo)digester.parse(is);

System.out.println(foo.getBarList().size());


 

我们来对第2中解析XML的方法做下分析:

1.遇到pattern匹配foo时候创建一个Foo对象,并压入栈中。

2.定义foo下属性到Foo对象成员变量的映射。

3.当遇到pattern为foo/bar的时候。创建一个Bar元素,再将Bar元素压入堆栈中。

4.定义bar下属性到Bar对象成员变量的映射。

5.完成一个Bar映射后,从栈里弹出Bar引用,这时栈的peek值为Foo的引用,于是addSetNext方法告诉我们,调用Foo对象引用的addBar元素,参数为Bar类的引用。

6.当把所有的映射处理完毕之后再弹出Foo对象。

7.digester处理完成后返回最外层的Foo对象的实例引用。

 

 

以上介绍了2种解析XML的方法,然后还更大家分享一种方法,就是digester的addRuleSet(RuleSet)方法,这个方法的参数是一个需要继承RuleSetBase的自定义类。并且要自己实现addRuleInstances(digester)方法,将digester的具体逻辑写在该回调方法里面即可。

 

至于命名空间的设置以及验证,在本文中不做详细解释。

 

希望以上总结的内容对大家有所帮助。

 

参考资料:http://commons.apache.org/digester/commons-digester-1.8/docs/api/org/apache/commons/digester/package-summary.html

 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息