實(shí)現(xiàn)這一功能的核心類是BeanReader,如果你看過betwixt的源代碼,你會(huì)發(fā)現(xiàn)
public class BeanReader extends Digester{}
如果你細(xì)看一下BeanReader的源代碼,你會(huì)發(fā)現(xiàn)betwixt在處理xml-->JavaBean轉(zhuǎn)化時(shí)其實(shí)是調(diào)用Digester這個(gè)類的parse方法。但除了此方式
可以實(shí)現(xiàn)轉(zhuǎn)化的功能以外,BeanReader自身也有一些新的機(jī)制對(duì)xml進(jìn)行轉(zhuǎn)化,完善了Digester的很多欠缺功能,讓轉(zhuǎn)化更加方便。
首先,來看一下BeanReader完全使用Digester的parse方法進(jìn)行轉(zhuǎn)化的流程。(其實(shí)覺得說是Digester怎樣處理轉(zhuǎn)化更為恰當(dāng))
1。xml信息
******************examples.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>
******************examples.xml*************************
2。定義實(shí)體對(duì)象Person和AddressBook
******************Person.java**************************
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);
}
}
******************Person.java**************************
******************AddressBook.java*********************
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();
}
}
}
******************AddressBook.java*********************
3。實(shí)現(xiàn)轉(zhuǎn)化功能
******************AddressBookDigester.java**************
public class AddressBookDigester{
public static void main(String[] args) throws IOException, SAXException, IntrospectionException{
// 創(chuàng)建一個(gè)BeanReader實(shí)例
BeanReader reader = new BeanReader();
// 創(chuàng)建AddressBook實(shí)例,并將其壓入棧頂。
AddressBook book = new AddressBook();
reader.push(book);
// 增加規(guī)則
addRules(reader);
reader.parse(new File("examples.xml"));
book.print();
}
private static void addRules(BeanReader d) {
// 當(dāng)遇到<person>時(shí),創(chuàng)建類Person的一個(gè)實(shí)例,并將其壓入棧頂
d.addObjectCreate("address-book/person", Person.class);
// 將<person>標(biāo)簽的屬性(attribute)與棧頂Person類對(duì)象的屬性(property)設(shè)置方法根據(jù)各自的名字進(jìn)行映射,(例如,將
標(biāo)簽屬性id與屬性設(shè)置方法setId進(jìn)行映射,將標(biāo)簽屬性category與屬性設(shè)置方法setCategory進(jìn)行映射),然后將屬性的值作參數(shù)傳遞給執(zhí)行相
應(yīng)的方法。
// 如果某標(biāo)簽屬性沒法通過名字找到相應(yīng)的屬性設(shè)置方法,則此標(biāo)簽屬性被忽略(如example.xml中第一個(gè)<person>的try屬
性)。
d.addSetProperties("address-book/person");
// 調(diào)用第二棧頂對(duì)象(AddressBook實(shí)例)的addPerson方法,以棧對(duì)象(Person實(shí)例)的對(duì)象為參數(shù)
d.addSetNext("address-book/person", "addPerson");
// 當(dāng)遇到<person>的子元素<name>時(shí),調(diào)用棧頂對(duì)象(Person實(shí)例)的setName方法。
// 此處addCallMethod方法的第一參數(shù)是規(guī)則,第二個(gè)參數(shù)是方法的名字,第三個(gè)是參數(shù)的數(shù)量(為0時(shí),表示只有一個(gè)參數(shù)
,且參數(shù)的值是元素的內(nèi)容)
d.addCallMethod("address-book/person/name", "setName", 0);
// 當(dāng)遇到<person>的子元素<email>時(shí),調(diào)用棧頂對(duì)象(Person實(shí)例)的addEmail
// 方法,addEmail方法有兩個(gè)參數(shù),取值分別來自<email>的屬性type的值和<email>本身的內(nèi)容。
// 此處addCallParam方法的第一參數(shù)是規(guī)則,第二個(gè)參數(shù)是指明被調(diào)用方法(addEmail)參數(shù)的序號(hào),第三個(gè)是參數(shù)為字符串
時(shí)指屬性的名字)
d.addCallMethod("address-book/person/email", "addEmail", 2);
d.addCallParam("address-book/person/email", 0, "type");
d.addCallParam("address-book/person/email", 1);
}
}
******************AddressBookDigester.java**************
運(yùn)行結(jié)果如下:
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()方法,對(duì)轉(zhuǎn)化屬性進(jìn)行配置的方式。
1。定義實(shí)體類
*************************PersonBean.java****************
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 + "‘]";
}
}
*************************PersonBean.java****************
2.person.xml文件
*************************person.xml*********************
<beans>
<personbean>
<age>22</age>
<name>luna</name>
</personbean>
</beans>
*************************person.xml*********************
3。實(shí)現(xiàn)轉(zhuǎn)化功能
*************************ReadApp.java*******************
import java.io.StringReader;
import org.apache.commons.betwixt.io.BeanReader;
public class ReadApp {
public static final void main(String args[]) throws Exception{
// 初始化BeanReader并對(duì)其進(jìn)行配置
BeanReader reader = new BeanReader();
reader.getXMLIntrospector().getConfiguration()
.setAttributesForPrimitives(false);
reader.getBindingConfiguration().setMapIDs(false);
// 注冊(cè)bean,告訴betwixt把xml轉(zhuǎn)化成什么bean
reader.registerBeanClass("personbean", PersonBean.class);
// 得到一個(gè)Object對(duì)象并打印
PersonBean person = (PersonBean)reader.parse(new File("person.xml"));
System.out.println(person);
}
}
*************************ReadApp.java*******************
運(yùn)行結(jié)果:
PersonBean[name=‘luna‘,age=‘22‘]
說明幾點(diǎn):
Digester類的parse()是xml向javabean轉(zhuǎn)化的核心方法,兩者的最大區(qū)別是,前者通過詳細(xì)的add***()方法,告訴了BeanReader的轉(zhuǎn)化步驟,而后者則是用registerBeanClass()注冊(cè)將要轉(zhuǎn)化成的bean對(duì)象類型,而其中的方法調(diào)用則是BeanReader自動(dòng)去按號(hào)入座完成的。而后者也一次只能轉(zhuǎn)化一個(gè)bean對(duì)象,可采用迭代的方法對(duì)多哥對(duì)象進(jìn)行操作。
前者適用于在已經(jīng)知道bean類型及具體屬性的情況下,可以用add***()一步步的設(shè)定轉(zhuǎn)化的步驟,而如果產(chǎn)生的對(duì)象是預(yù)先未知的,只有在知道結(jié)果的情況下才知道它的屬性,這個(gè)時(shí)候只要在后者方法中使用registerBeanClass()把該類注冊(cè)給betwxit,剩下的功能,這個(gè)組件就可以自動(dòng)完成了 。
聯(lián)系客服