正文
在我们的项目中或多或少会采用xml来做配置文件,你可以采用Java原生支持的sax、DOM或者第三方的dom4j等。虽然提供了各式各样的解析方式,但是解析一个复杂的xml所编写的Java代码是非常麻烦的,尤其是当xml做了修改,你会发现你又要修改Java代码。
Apache的commons项目中Digester项目解决了这个问题,它可以很轻易地将xml文件解析成Java对象,让你直接去使用,而你仅仅需要去预定义一份解析规则。
而对于解析规则,你可以采用Java的方式定义、xml的方式定义亦或者annotation的方式定义。
要使用digester需要引入依赖:
<!--apache commons digester-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-digester3</artifactId>
<version>3.2</version>
</dependency>
假设我们要解析如下school.xml文件

<?xml version="1.0" encoding="utf-8" ?>
<school>
<classes>
<class className="classOne">
<student>
<no>1</no>
<name>小张</name>
<age>24</age>
</student>
<student>
<no>2</no>
<name>小李</name>
<age>24</age>
</student>
<student>
<no>1</no>
<name>小王</name>
<age>24</age>
</student>
</class>
</classes>
</school>

我们需要预定义Student、Class、School节点的Java类与之对应

package cn.lay.demo.digester.definition;
/**
* 学生节点
* @author lay
* @date 2018/10/16 23:35
*/
public class StudentDefinition {
private Integer no;
private String name;
private Integer age;
public Integer getNo() {
return no;
}
public void setNo(Integer no) {
this.no = no;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "StudentDefinition{" +
"no=" + no +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
package cn.lay.demo.digester.definition;
import java.util.ArrayList;
import java.util.List;
/**
* 班级节点
* @author lay
* @date 2018/10/16 23:36
*/
public class ClassDefinition {
private String className;
private List<StudentDefinition> studentDefinitionList = new ArrayList<>();
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public List<StudentDefinition> getStudentDefinitionList() {
return studentDefinitionList;
}
public void setStudentDefinitionList(List<StudentDefinition> studentDefinitionList) {
this.studentDefinitionList = studentDefinitionList;
}
public void addStudent(StudentDefinition studentDefinition) {
studentDefinitionList.add(studentDefinition);
}
@Override
public String toString() {
return "ClassDefinition{" +
"className='" + className + '\'' +
", studentDefinitionList=" + studentDefinitionList +
'}';
}
}
package cn.lay.demo.digester.definition;
import java.util.ArrayList;
import java.util.List;
/**
* 学校节点
* @author lay
* @date 2018/10/16 23:37
*/
public class SchoolDefinition {
private List<ClassDefinition> classDefinitions = new ArrayList<>();
public List<ClassDefinition> getClassDefinitions() {
return classDefinitions;
}
public void setClassDefinitions(List<ClassDefinition> classDefinitions) {
this.classDefinitions = classDefinitions;
}
public void addClass(ClassDefinition classDefinition) {
classDefinitions.add(classDefinition);
}
@Override
public String toString() {
return "SchoolDefinition{" +
"classDefinitions=" + classDefinitions +
'}';
}
}

1、Java方式配置解析规则
rule

package cn.lay.demo.digester.rule;
import cn.lay.demo.digester.definition.ClassDefinition;
import cn.lay.demo.digester.definition.SchoolDefinition;
import cn.lay.demo.digester.definition.StudentDefinition;
import org.apache.commons.digester3.Digester;
import java.net.URL;
/**
* java方式定义解析规则
* @author lay
* @date 2018/10/16 23:38
*/
public class DigesterRule {
/**
* 解析
* @param filePath
* @return
*/
public SchoolDefinition execute(String filePath) throws Exception{
Digester digester = new Digester();
digester.setValidating(false);
// classes node
digester.addObjectCreate("school/classes", SchoolDefinition.class);
// class node
digester.addObjectCreate("school/classes/class", ClassDefinition.class);
// set properties
digester.addSetProperties("school/classes/class");
// student node
digester.addObjectCreate("school/classes/class/student", StudentDefinition.class);
// set properties
digester.addBeanPropertySetter("school/classes/class/student/no");
digester.addBeanPropertySetter("school/classes/class/student/name");
digester.addBeanPropertySetter("school/classes/class/student/age");
// add student
digester.addSetNext("school/classes/class/student", "addStudent");
// add class
digester.addSetNext("school/classes/class", "addClass");
// parse
URL url = this.getClass().getClassLoader().getResource(filePath);
System.out.println("url=" + url.toString());
return digester.parse(url);
}
}

测试
@Test
public void testJavaRule() throws Exception {
SchoolDefinition schoolDefinition = new DigesterRule().execute("school.xml");
System.out.println(schoolDefinition);
}
2、xml方式配置解析规则
rule

<!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>
<!--school node-->
<pattern value="school/classes">
<object-create-rule classname="cn.lay.demo.digester.definition.SchoolDefinition"/>
<!--class node-->
<pattern value="class">
<object-create-rule classname="cn.lay.demo.digester.definition.ClassDefinition"/>
<set-properties-rule/>
<!--student node-->
<pattern value="student">
<object-create-rule classname="cn.lay.demo.digester.definition.StudentDefinition"/>
<bean-property-setter-rule pattern="no"/>
<bean-property-setter-rule pattern="name"/>
<bean-property-setter-rule pattern="age"/>
<set-next-rule methodname="addStudent"/>
</pattern>
<set-next-rule methodname="addClass"/>
</pattern>
</pattern>
</digester-rules>

测试

@Test
public void testXmlRule() throws Exception {
Digester digester = DigesterLoader.newLoader(new XmlRulesModule()).newDigester();
URL url = this.getClass().getClassLoader().getResource("school.xml");
System.out.println("url=" + url);
SchoolDefinition schoolDefinition = digester.parse(url);
System.out.println(schoolDefinition);
}
class XmlRulesModule extends FromXmlRulesModule {
@Override
protected void loadRules() {
loadXMLRules(this.getClass().getClassLoader().getResourceAsStream("rule/schoolRule.xml"));
}
}

3、注解方式配置解析规则
基于零配置思想,digester支持采用annotation来注解相应的解析规则。
rule

package cn.lay.demo.digester.definition;
import org.apache.commons.digester3.annotations.rules.ObjectCreate;
import org.apache.commons.digester3.annotations.rules.SetNext;
import org.apache.commons.digester3.annotations.rules.SetRoot;
import java.util.ArrayList;
import java.util.List;
/**
* 学校节点
* @author lay
* @date 2018/10/16 23:37
*/
@ObjectCreate(pattern = "school/classes")
public class SchoolDefinition {
private List<ClassDefinition> classDefinitions = new ArrayList<>();
public List<ClassDefinition> getClassDefinitions() {
return classDefinitions;
}
public void setClassDefinitions(List<ClassDefinition> classDefinitions) {
this.classDefinitions = classDefinitions;
}
@SetNext
public void addClass(ClassDefinition classDefinition) {
System.out.println("执行了addClass");
classDefinitions.add(classDefinition);
}
@Override
public String toString() {
return "SchoolDefinition{" +
"classDefinitions=" + classDefinitions +
'}';
}
}
package cn.lay.demo.digester.definition;
import org.apache.commons.digester3.annotations.rules.*;
import java.util.ArrayList;
import java.util.List;
/**
* 班级节点
* @author lay
* @date 2018/10/16 23:36
*/
@ObjectCreate(pattern = "school/classes/class")
public class ClassDefinition {
@SetProperty(pattern = "school/classes/class")
private String className;
private List<StudentDefinition> studentDefinitionList = new ArrayList<>();
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public List<StudentDefinition> getStudentDefinitionList() {
return studentDefinitionList;
}
public void setStudentDefinitionList(List<StudentDefinition> studentDefinitionList) {
this.studentDefinitionList = studentDefinitionList;
}
@SetNext
public void addStudent(StudentDefinition studentDefinition) {
System.out.println("执行了addStudent");
studentDefinitionList.add(studentDefinition);
}
@Override
public String toString() {
return "ClassDefinition{" +
"className='" + className + '\'' +
", studentDefinitionList=" + studentDefinitionList +
'}';
}
}
package cn.lay.demo.digester.definition;
import org.apache.commons.digester3.annotations.rules.BeanPropertySetter;
import org.apache.commons.digester3.annotations.rules.ObjectCreate;
/**
* 学生节点
* @author lay
* @date 2018/10/16 23:35
*/
@ObjectCreate(pattern = "school/classes/class/student")
public class StudentDefinition {
@BeanPropertySetter(pattern = "school/classes/class/student/no")
private Integer no;
@BeanPropertySetter(pattern = "school/classes/class/student/name")
private String name;
@BeanPropertySetter(pattern = "school/classes/class/student/age")
private Integer age;
public Integer getNo() {
return no;
}
public void setNo(Integer no) {
this.no = no;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "StudentDefinition{" +
"no=" + no +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}

测试

@Test
public void testAnnotationRule() throws Exception {
Digester digester = DigesterLoader.newLoader(new FromAnnotationsRuleModule() {
@Override
protected void configureRules() {
// 这里只添加SchoolDefinition即可
bindRulesFrom(SchoolDefinition.class);
}
}).newDigester();
URL url = this.getClass().getClassLoader().getResource("school.xml");
System.out.println("url=" + url);
SchoolDefinition schoolDefinition = digester.parse(url);
System.out.println(schoolDefinition);
}

本文介绍Apache Commons Digester库,用于将复杂XML文件解析为Java对象。通过Java配置、XML配置和注解三种方式定义解析规则,简化XML到Java对象的转换过程。
292

被折叠的 条评论
为什么被折叠?



