使用Apache Digester相当容易将XML文档转换为相应的Java bean对象层次结构。 请参阅下面的“摘要”。
Digester引入了三个重要概念:
- 元素匹配模式
- 处理规则
- 对象堆栈。
元素匹配模式将 XML元素与处理规则相关联。
范例:
你有什么:
- Java类
- 包含数据的XML文件
您有Java类和相应的xml文件。 您希望从xml数据创建Java类实例。
您需要编写哪些额外的代码。
分步任务:
- 在类路径中添加Apache Digester 3 jar文件,Commons日志jar,Beanutils jar,cglib jar
- 如果没有Java类,则为相应的xml文件创建Java类。或者,如果没有xml文件,则根据java类创建。注-属性名称,xml和java类中的层次结构应匹配,否则,需要在此处未提及的摘要XML规则中提供映射。
- 如以下示例中所述,创建摘要规则XML文件
- 用几行来从XML加载Java对象
现在在行动–
这是我的Eclipse项目结构:
任务2 –如下创建数据xml文件,您要从中加载数据, 例如– chain-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<catalogs>
<!-- Default Catalog: "Path Info" example -->
<catalog>
<!-- Command that maps "Path Info" patterns to Commands -->
<chain name="COMMAND_MAPPER">
<command className="org.apache.commons.chain.web.servlet.PathInfoMapper"/>
<command forward="/pathinfo.jsp" className="org.apache.commons.chain.apps.example.ForwardCommand"/>
</chain>
<!-- Foo Command -->
<chain name="/foo">
<command attribute="pathinfoFooCount" className="org.apache.commons.chain.apps.example.CountCommand"/>
</chain>
<!-- Bar Command -->
<chain name="/bar">
<command attribute="pathinfoBarCount" className="org.apache.commons.chain.apps.example.CountCommand"/>
</chain>
</catalog>
<!-- Catalog for "Request Parameter" example -->
<catalog name="reqparam">
<!-- Command that maps a "Request Parameter" to Commands -->
<chain name="COMMAND_MAPPER">
<command catalogName="reqparam" className="org.apache.commons.chain.web.servlet.RequestParameterMapper"/>
<command forward="/reqparam.jsp" className="org.apache.commons.chain.apps.example.ForwardCommand"/>
</chain>
<!-- Foo Command -->
<chain name="foo">
<command attribute="reqparamFooCount" className="org.apache.commons.chain.apps.example.CountCommand"/>
</chain>
<!-- Bar Command -->
<chain name="bar">
<command attribute="reqparamBarCount" className="org.apache.commons.chain.apps.example.CountCommand"/>
</chain>
</catalog>
</catalogs>
创建相应的Java类 Catalog.java:
import java.util.ArrayList;
import java.util.List;
public class Catalog {
/**
* @uml.property name="name"
*/
private String name;
/**
* Getter of the property <tt>name</tt>
* @return Returns the name.
* @uml.property name="name"
*/
public String getName() {
return name;
}
/**
* Setter of the property <tt>name</tt>
* @param name The name to set.
* @uml.property name="name"
*/
public void setName(String name) {
this.name = name;
}
/**
* @uml.property name="chains"
*/
private List<Chain> chains=new ArrayList<Chain>();
public void addChains(Chain chain)
{
this.chains.add(chain);
}
}
Chain.java:
import java.util.ArrayList;
import java.util.List;
public class Chain {
/**
* @uml.property name="name"
*/
private String name;
/**
* Getter of the property <tt>name</tt>
* @return Returns the name.
* @uml.property name="name"
*/
public String getName() {
return name;
}
/**
* Setter of the property <tt>name</tt>
* @param name The name to set.
* @uml.property name="name"
*/
public void setName(String name) {
this.name = name;
}
/**
* @uml.property name="commands"
*/
private List<Command> commands=new ArrayList<Command>();
/**
* Setter of the property <tt>commands</tt>
* @param commands The commands to set.
* @uml.property name="commands"
*/
public void addCommands(Command command) {
this.commands.add(command);
}
}
Command.java:
import java.util.ArrayList;
import java.util.List;
public class Chain {
/**
* @uml.property name="name"
*/
private String name;
/**
* Getter of the property <tt>name</tt>
* @return Returns the name.
* @uml.property name="name"
*/
public String getName() {
return name;
}
/**
* Setter of the property <tt>name</tt>
* @param name The name to set.
* @uml.property name="name"
*/
public void setName(String name) {
this.name = name;
}
/**
* @uml.property name="commands"
*/
private List<Command> commands=new ArrayList<Command>();
/**
* Getter of the property <tt>commands</tt>
* @return Returns the commands.
* @uml.property name="commands"
*/
public List getCommands() {
return commands;
}
/**
* Setter of the property <tt>commands</tt>
* @param commands The commands to set.
* @uml.property name="commands"
*/
public void addCommands(Command command) {
this.commands.add(command);
}
}
任务3 –创建 摘要程序 规则 digester-catalog-rules.xml
<?xml version="1.0"?>
<!DOCTYPE digester-rules PUBLIC
"-//Apache Commons //DTD digester-rules XML V1.0//EN"
"http://commons.apache.org/digester/dtds/digester-rules-3.0.dtd">
<digester-rules>
<pattern value="catalogs/catalog">
<object-create-rule classname="Catalog"/>
<set-properties-rule/>
<!-- comment :
<bean-property-setter-rule pattern="name"/>
use as shown above if say <catalog><name>reparam</name> </catalog> instead of <catalog name="reparam"> </catalog>
-->
<!-- Nested Pattern for Characters -->
<pattern value="chain">
<object-create-rule classname="Chain"/>
<set-properties-rule/>
<!-- Nested Pattern for Characters -->
<pattern value="command">
<object-create-rule classname="Command"/>
<set-properties-rule/>
<set-next-rule methodname="addCommands" paramtype="Command"/>
</pattern>
<set-next-rule methodname="addChains" paramtype="Chain"/>
</pattern>
<set-next-rule methodname="add" paramtype="Catalog"/>
</pattern>
</digester-rules>
任务4 –加载xml数据的客户端程序
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import org.apache.commons.digester3.Digester;
import org.apache.commons.digester3.binder.DigesterLoader;
import org.apache.commons.digester3.xmlrules.FromXmlRulesModule;
import org.xml.sax.SAXException;
import java.util.ArrayList;
import java.util.List;
public class runProgram {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
// Create an instance of the Digester from the XML rule set
DigesterLoader digesterLoader = DigesterLoader.newLoader(new FromXmlRulesModule() {
@Override
protected void loadRules() {
// TODO Auto-generated method stub
loadXMLRules( getClass( ).getResource("/com/tatu/resources/digester-catalog-rules.xml"));
}
});
Digester digester = digesterLoader.newDigester();
List<Catalog> catalogs = new ArrayList<Catalog>();
// Push a reference to the plays List on to the Stack
digester.push(catalogs);
// Parse the XML document
InputStream input = Digester.class.getClass().getResourceAsStream("/com/tatu/resources/chain-config.xml");
try {
Object root = digester.parse(input);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
做完了 因此,已经用xml数据加载了catalogs对象。
上述解决方案要注意的几点:
- object-create-rule创建一个对象
- 其余规则如其名称所暗示的那样简单明了:object-create-rule创建一个新实例,set-properties-rule从xml属性(如目录元素的name属性)设置对象的属性,而bean-property-setter-rule设置嵌套xml元素中对象的属性,例如<catalog> <name> reparam </ name> </ catalog>而不是<catalog name ='reparam'> </ catalog>
- – set-next-rule :(用于递归)set-next-rulerule移至下一个目录,链和命令标签。 您还指定了每种情况下要调用的方法,该方法会将对象添加到父类中定义的集合中,例如:<set-next-rule methodname ='addCommands'paramtype ='Command'/>,此处为addCommands()方法将命令对象添加到父链类中定义的命令收集对象。
- 您需要新的自定义规则,请创建自摘要器Rule类派生的自己的Rule类。
有任何问题,请发表您的评论。
再想一想,您不希望在xml文件和java类之间出现所有这些问题。 猜猜怎么着,有个避免的办法。 但是除非您着急,否则我不喜欢这个把戏。 但是,每次使用快捷方式时,都必须失去灵活性。
技巧是使用Apache Betwixt。 记住要使用Betwixt,您需要使用Apache Digester 2.1。 有关更多信息,请访问apache Betwixt网站。
使用Betwixt BeanWriter将Java Bean写入文件,然后使用BeanReader从该文件读取。 从BeanWriter生成文件后,就可以更改值,并在BeanReader中加载该文件。 (需要在此处省略配置之间的映射)
祝您编程愉快,别忘了分享!
参考:在我的软件开发博客博客上,来自我们的JCG合作伙伴 Bijay Deo的示例中使用Apache Digester-轻松进行配置 。
翻译自: https://www.javacodegeeks.com/2012/09/apache-digester-example-make-easy.html