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
test1.xml
处理方法:
根据最后的处理方法我们来做一番分析:
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
Bar.java
test2.xml
处理方法:
我们来对第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
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
相关文章推荐
- Apache开源项目之1[BeanUtils使用]
- 地址主题java项目中添加邮件发送功能(使用apache commons mail开源项目)
- 前端开发的使用服务器环境开源项目 D2Server 可替代Apache
- 推荐一个前端开发的使用服务器环境开源项目 D2Server 可替代Apache
- 推荐前端开发使用的服务器环境开源项目 D2Server 可替代Apache
- java项目中添加邮件发送功能(使用apache commons mail开源项目)
- org.apache.commons.digester.Digester使用 [待续]
- Android SlidingMenu 开源项目 侧拉菜单的使用(详细配置)
- Restful.Data 开源持久层组件项目最新进展和使用说明
- 关于使用开源项目SlidingMenu的问题
- android开源项目---SlidingMenu环境的搭建与使用
- 开源项目material-dialogs使用
- LeakCanary开源项目(使用及原理github项目文档的翻译)
- Mac下教你如何使用Github客户端开源项目
- android-async-http开源项目介绍及使用方法
- apache开源项目--ibatis
- 使用自定义工具链toolchain编译开源项目
- apache开源项目--gora
- apache开源项目--ZooKeeper
- 优秀开源项目SwipeLayout的使用