前言
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