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