首页 > 代码库 > Apache Commons Digester 三(规则注解)

Apache Commons Digester 三(规则注解)

前言

Digester规则的定义除了可以在代码中直接new规则添加到 Digester对象外,还可以用xml配置规则,如下所示:

<digester-rules>  <pattern value="*/foo">    <object-create-rule pattern="bar" classname="Foobar" />    <set-properties-rule pattern="bar" />  </pattern></digester-rules>

显然,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文件:

<rss version="2.0">    <channel>        <title>Apache</title>        <link>http://www.apache.org</link>        <description>The Apache Software Foundation</description>        <language>en-US</language>        <rating>(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))        </rating>        <image>            <title>Apache</title>            <url>http://jakarta.apache.org/images/jakarta-logo.gif</url>            <link>http://jakarta.apache.org</link>            <width>505</width>            <height>480</height>            <description>The Jakarta project. Open source, serverside java.            </description>        </image>        <item>            <title>Commons Attributes 2.1 Released</title>            <link>http://jakarta.apache.org/site/news/news-2004-2ndHalf.html#20040815.1            </link>            <description>The 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.            </description>        </item>        <item>            <title>Cloudscape Becomes Apache Derby</title>            <link>http://jakarta.apache.org/site/news/elsewhere-2004-2ndHalf.html#20040803.1            </link>            <description>IBM has submitted a proposal to the Apache DB project                for a Java-based package to be called ‘Derby‘.</description>        </item>        <item>            <title>Commons BeanUtils 1.7 Released</title>            <link>http://jakarta.apache.org/site/news/news-2004-2ndHalf.html#20040802.1            </link>            <description />        </item>        <item>            <title>Commons JXPath 1.2 Released</title>            <link>http://jakarta.apache.org/site/news/news-2004-2ndHalf.html#20040801.2            </link>            <description />        </item>    </channel></rss>

首先,观察分析要解析的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<Item> items = new ArrayList<Item>();    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<Item> 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插件模块(感觉很少会使用,不过参考代码里有例子)没详细说明外,基本涵盖了所有内容;

有兴趣的还可以深入研究,看看源码,相对而言也不难;

参考资料

http://commons.apache.org/proper/commons-digester/guide/annotations.html

参考代码

https://github.com/peterchenhdu/apache-commons-digester-example

 

Apache Commons Digester 三(规则注解)