前言
Digester规则的定义除了可以在代码中直接new规则添加到 Digester对象外,还可以用xml配置规则,如下所示:
显然,xml的规则配置目前已经不是主流方法了,今后的大趋势肯定是用注解,所以本文将主要关注如何在javabean上使用注解来配置Digester规则;
Digester规则注解
简单描述下Digester 有哪几类注解,详细信息建议看api文档,其实也比较简单了,熟悉Digester规则的话,基本不用看也知道;
类型注解
- @ObjectCreate 绑定Digester的
ObjectCreateRule
规则 - @FactoryCreate 绑定Digester的FactoryCreateRule规则
属性注解
- @BeanPropertySetter
绑定Digester的
BeanPropertySetterRule
规则 - @SetProperty
绑定Digester的SetPropertiesRule规则
方法注解
- @CallMethod ----> org.apache.commons.digester3.CallMethodRule
- @SetNext ----> org.apache.commons.digester3.SetNextRule
- @SetRoot ----> org.apache.commons.digester3.SetRootRule
- @SetTop ----> org.apache.commons.digester3.SetTopRule
参数注解
- @CallParam ----> org.apache.commons.digester3.rule.CallParamRule
Digester注解例子
看了半天,可能也还没有清晰直观的认识,直接看个例子,基本也就差不多了
如下是我们要解析的xml文件:
Apache http://www.apache.orgThe Apache Software Foundation en-US (PICS-1.1 "http://www.rsac.org/ratingsv01.html" 2 gen true comment "RSACi North America Server" for "http://www.rsac.org" on "1996.04.16T08:15-0500" r (n 0 s 0 v 0 l 0)) Apache http://jakarta.apache.org/images/jakarta-logo.gif http://jakarta.apache.org505 480 The Jakarta project. Open source, serverside java. Commons Attributes 2.1 Released http://jakarta.apache.org/site/news/news-2004-2ndHalf.html#20040815.1The Apache Commons team is happy to announce the release of Commons Attributes 2.1. This is the first release of the new Commons-Attributes code. Cloudscape Becomes Apache Derby http://jakarta.apache.org/site/news/elsewhere-2004-2ndHalf.html#20040803.1IBM has submitted a proposal to the Apache DB project for a Java-based package to be called 'Derby'. Commons BeanUtils 1.7 Released http://jakarta.apache.org/site/news/news-2004-2ndHalf.html#20040802.1Commons JXPath 1.2 Released http://jakarta.apache.org/site/news/news-2004-2ndHalf.html#20040801.2
首先,观察分析要解析的xml文档,创建javabean对象,加上Digester元注解,
先创建一个Channel对象,如下所示,感觉也不需要过多解析,很直观了,注意下@SetNext注解,是根据方法参数对象里定义的注解匹配的
package apache.commons.digester3.example.annotations;import java.util.ArrayList;import java.util.List;import org.apache.commons.digester3.annotations.rules.BeanPropertySetter;import org.apache.commons.digester3.annotations.rules.ObjectCreate;import org.apache.commons.digester3.annotations.rules.SetNext;/** * * * @author http://www.cnblogs.com/chenpi/ * @version 2017年6月7日 */@ObjectCreate(pattern = "rss/channel")public class Channel{ private final List- items = new ArrayList
- (); private Image image; @BeanPropertySetter(pattern = "rss/channel/title") private String title; @BeanPropertySetter(pattern = "rss/channel/link") private String link; @BeanPropertySetter(pattern = "rss/channel/description") private String description; @BeanPropertySetter(pattern = "rss/channel/language") private String language; @SetNext public void setImage(Image image) { this.image = image; } @SetNext public void addItem(Item item) { this.items.add(item); } /** * @return the title */ public String getTitle() { return title; } /** * @param title the title to set */ public void setTitle(String title) { this.title = title; } /** * @return the link */ public String getLink() { return link; } /** * @param link the link to set */ public void setLink(String link) { this.link = link; } /** * @return the description */ public String getDescription() { return description; } /** * @param description the description to set */ public void setDescription(String description) { this.description = description; } /** * @return the language */ public String getLanguage() { return language; } /** * @param language the language to set */ public void setLanguage(String language) { this.language = language; } /** * @return the items */ public List
- getItems() { return items; } /** * @return the image */ public Image getImage() { return image; }}
在定义两个对象Image和Item,如下所示,至此,我们就已经把xml中所有元素需要匹配的规则定义完了
package apache.commons.digester3.example.annotations;import org.apache.commons.digester3.annotations.rules.BeanPropertySetter;import org.apache.commons.digester3.annotations.rules.ObjectCreate;/** * * * @author http://www.cnblogs.com/chenpi/ * @version 2017年6月7日 */@ObjectCreate(pattern = "rss/channel/item")public class Item{ @BeanPropertySetter(pattern = "rss/channel/item/description") private String description; @BeanPropertySetter(pattern = "rss/channel/item/link") private String link; @BeanPropertySetter(pattern = "rss/channel/item/title") private String title; /** * @return the description */ public String getDescription() { return description; } /** * @param description the description to set */ public void setDescription(String description) { this.description = description; } /** * @return the link */ public String getLink() { return link; } /** * @param link the link to set */ public void setLink(String link) { this.link = link; } /** * @return the title */ public String getTitle() { return title; } /** * @param title the title to set */ public void setTitle(String title) { this.title = title; }}
package apache.commons.digester3.example.annotations;import org.apache.commons.digester3.annotations.rules.BeanPropertySetter;import org.apache.commons.digester3.annotations.rules.ObjectCreate;/** * * * @author http://www.cnblogs.com/chenpi/ * @version 2017年6月7日 */@ObjectCreate(pattern = "rss/channel/image")public class Image{ @BeanPropertySetter(pattern = "rss/channel/image/description") private String description; @BeanPropertySetter(pattern = "rss/channel/image/width") private int width; @BeanPropertySetter(pattern = "rss/channel/image/height") private int height; @BeanPropertySetter(pattern = "rss/channel/image/link") private String link; @BeanPropertySetter(pattern = "rss/channel/image/title") private String title; @BeanPropertySetter(pattern = "rss/channel/image/url") private String url; /** * @return the description */ public String getDescription() { return description; } /** * @param description the description to set */ public void setDescription(String description) { this.description = description; } /** * @return the width */ public int getWidth() { return width; } /** * @param width the width to set */ public void setWidth(int width) { this.width = width; } /** * @return the height */ public int getHeight() { return height; } /** * @param height the height to set */ public void setHeight(int height) { this.height = height; } /** * @return the link */ public String getLink() { return link; } /** * @param link the link to set */ public void setLink(String link) { this.link = link; } /** * @return the title */ public String getTitle() { return title; } /** * @param title the title to set */ public void setTitle(String title) { this.title = title; } /** * @return the url */ public String getUrl() { return url; } /** * @param url the url to set */ public void setUrl(String url) { this.url = url; } // getters and setters}
规则与javabean绑定完后,就可以开始解析了,注意我们这里使用DigesterLoader来创建Digester实例对象,而DigesterLoader实例是通过FromAnnotationsRuleModule创建的,该类允许我们从一个注解的类上加载规则集:
/* * File Name: Main.java * Description: * Author: http://www.cnblogs.com/chenpi/ * Create Date: 2017年6月7日 */package apache.commons.digester3.example.annotations;import org.apache.commons.digester3.Digester;import org.apache.commons.digester3.annotations.FromAnnotationsRuleModule;import org.apache.commons.digester3.binder.DigesterLoader;/** * * @author http://www.cnblogs.com/chenpi/ * @version 2017年6月7日 */public class Main{ public static void main(String[] args) { try { DigesterLoader loader = DigesterLoader.newLoader(new FromAnnotationsRuleModule() { @Override protected void configureRules() { bindRulesFrom(Channel.class); } }); Digester digester = loader.newDigester(); Channel channel = digester .parse(Main.class.getClassLoader().getResourceAsStream("rss.xml")); System.out.println(channel.getTitle()); System.out.println(channel.getImage().getDescription()); } catch (Exception e) { e.printStackTrace(); } }}
结语
至此,Digester 的学习就告一段落了,除了使用xml定义规则(有注解了,感觉没必要在使用xml配置规则)和Digester插件模块(感觉很少会使用,不过参考代码里有例子)没详细说明外,基本涵盖了所有内容;
有兴趣的还可以深入研究,看看源码,相对而言也不难;
参考资料
参考代码