跑步

实现xml信息到Java Bean的转化

2019-09-11 15:24:22来源:励志吧0次阅读

本文主要是关于使用commons-betwixt组件实现xml信息到Java Bean的转化的一些感受,实现这一功能的核心类是BeanReader,如果你看过betwixt的源代码,你会发现public class BeanReader extends Digester{}

如果你细看一下BeanReader的源代码,betwixt在处理xml-->JavaBean转化时其实是调用Digester这个类的parse方法。但除了此方式可以实现转化的功能以外,BeanReader自身也有一些新的机制对xml进行转化,完善了Digester的很多欠缺功能,让转化更加方便。

首先,来看一下BeanReader完全使用Digester的parse方法进行转化的流程。(其实觉得说是Digester怎样处理转化更为恰当)

1。xml信息

<address-book>

<person id="1" category="acquaintance" try="would be ignored">

<name>Gonzo</name>

<email type="business">gonzo@muppets.com</email>

<gender result="the whole tag would be ignored">male</gender>

</person>

<person id="2" category="rolemodel">

<name>Kermit</name>

<email type="business">kermit@muppets.com</email>

<email type="home">kermie@acme.com</email>

</person>

</address-book>

2。定义实体对象Person和AddressBook

import java.util.HashMap;

import java.util.Iterator;

public class Person {

private int id;

private String category;

private String name;

private HashMap emails = new HashMap();

/**

* A unique id for this person. Note that the Digester automatically

* converts the id to an integer.

*/

public void setId(int id) {

this.id = id;

}

public void setCategory(String category) {

this.category = category;

}

public void setName(String name) {

this.name = name;

}

/** we assume only one email of each type... */

public void addEmail(String type, String address) {

emails.put(type, address);

}

public void print() {

System.out.println("Person #" + id);

System.out.println(" category=" + category);

System.out.println(" name=" + name);

for(Iterator i = emails.keySet().iterator(); i.hasNext(); ) {

String type = (String) i.next();

String address = (String) emails.get(type);

System.out.println(" email (type " + type + ") : " + address);

}

}

import java.util.Iterator;

import java.util.LinkedList;

public class AddressBook {

LinkedList person = new LinkedList();

public LinkedList getPerson(){

return person;

}

public void addPerson(Person p) {

person.addLast(p);

}

public void print() {

System.out.println("Address book has " + person.size() + " entries");

for(Iterator i = person.iterator(); i.hasNext(); ) {

Person p = (Person) i.next();

p.print();

}

}

3。实现转化功能

public class AddressBookDigester{

public static void main(String[] args) throws IOException, SAXException, IntrospectionException{

// 创建一个BeanReader实例

BeanReader reader = new BeanReader();

// 创建AddressBook实例,并将其压入栈顶。

AddressBook book = new AddressBook();

reader.push(book);

// 增加规则

addRules(reader);

reader.parse(new File("examples.xml"));

book.print();

}

private static void addRules(BeanReader d) {

// 当遇到<person>时,创建类Person的一个实例,并将其压入栈顶

d.addObjectCreate("address-book/person", Person.class);

// 将<person>标签的属性(attribute)与栈顶Person类对象的属性(property)设置方法根据各自的名字进行映射,(例如,将

标签属性id与属性设置方法setId进行映射,将标签属性category与属性设置方法setCategory进行映射),然后将属性的值作参数传递给执行相

应的方法。

// 如果某标签属性没法通过名字找到相应的属性设置方法,则此标签属性被忽略(如example.xml中第一个<person>的try属

性)。

d.addSetProperties("address-book/person");

// 调用第二栈顶对象(AddressBook实例)的addPerson方法,以栈对象(Person实例)的对象为参数

d.addSetNext("address-book/person", "addPerson");

// 当遇到<person>的子元素<name>时,调用栈顶对象(Person实例)的setName方法。

// 此处addCallMethod方法的第一参数是规则,第二个参数是方法的名字,第三个是参数的数量(为0时,表示只有一个参数

,且参数的值是元素的内容)

d.addCallMethod("address-book/person/name", "setName", 0);

// 当遇到<person>的子元素<email>时,调用栈顶对象(Person实例)的addEmail

// 方法,addEmail方法有两个参数,取值分别来自<email>的属性type的值和<email>本身的内容。

// 此处addCallParam方法的第一参数是规则,第二个参数是指明被调用方法(addEmail)参数的序号,第三个是参数为字符串

时指属性的名字)

d.addCallMethod("address-book/person/email", "addEmail", 2);

d.addCallParam("address-book/person/email", 0, "type");

d.addCallParam("address-book/person/email", 1);

}

}

运行结果如下:

Address book has 2 entries

Person #1

category=acquaintance

name=Gonzo

email (type business) : gonzo@muppets.com

Person #2

category=rolemodel

name=Kermit

email (type business) : kermit@muppets.com

email (type home) : kermie@acme.com

其次,再看看不使用Digester的add***Method()方法,对转化属性进行配置的方式。

1。定义实体类

public class PersonBean {

private String name;

private int age;

/** Need to allow bean to be created via reflection */

public PersonBean() {}

public PersonBean(String name, int age) {

this.name = name;

this.age = age;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

public String toString() {

return "PersonBean[name='" + name + "',age='" + age + "']";

}

}

2.person.xml文件

<beans>

<personbean>

<age>22</age>

<name>luna</name>

</personbean>

</beans>

3。实现转化功能

import java.io.StringReader;

import org.apache.commons.betwixt.io.BeanReader;

public class ReadApp {

public static final void main(String args[]) throws Exception{

// 初始化BeanReader并对其进行配置

BeanReader reader = new BeanReader();

reader.getXMLIntrospector().getConfiguration()

.setAttributesForPrimitives(false);

reader.getBindingConfiguration().setMapIDs(false);

// 注册bean,告诉betwixt把xml转化成什么bean

reader.registerBeanClass("personbean", PersonBean.class);

// 得到一个Object对象并打印

PersonBean person = (PersonBean)reader.parse(new File("person.xml"));

System.out.println(person);

}

}

运行结果:

PersonBean[name='luna',age='22']

说明几点:

Digester类的parse()是xml向javabean转化的核心方法,两者的最大区别是,前者通过详细的add***()方法,告诉了BeanReader的转化步骤,而后者则是用registerBeanClass()注册将要转化成的bean对象类型,而其中的方法调用则是BeanReader自动去按号入座完成的。而后者也一次只能转化一个bean对象,可采用迭代的方法对多哥对象进行操作。

前者适用于在已经知道bean类型及具体属性的情况下,可以用add***()一步步的设定转化的步骤,而如果产生的对象是预先未知的,只有在知道结果的情况下才知道它的属性,这个时候只要在后者方法中使用registerBeanClass()把该类注册给betwxit,剩下的功能,这个组件就可以自动完成了 。

的了脑梗塞怎么办
孩子积食吃什么药好
儿童反复发烧
孩子高烧不退怎么办
分享到: