作者:王恩建 XML 在現在 Java 應用的開(kāi)發(fā)中,很多地方都能看到它的身影,比如最常見(jiàn)的是我們定義參數配置文件用的就是 XML 文件格式,避免程序的硬編碼。當然,XML 的應用不僅限于此,在其他技術(shù)領(lǐng)域 XML 也占有舉足輕重的位置。如何在 Java 中處理 XML 文件?目前最基礎最底層的 API 是 DOM, SAX, JDOM, dom4j。這些 API 為 Java 處理 XML 提供了解決方案,但是不足的是他們使用方法復雜,在處理 XML 的時(shí)候很容易發(fā)生錯誤。記得在兩年前使用 Cocoon 1.8 的時(shí)候,因為遺留系統采用 DOM 定義 XML 數據文件格式,大量的子元素、父元素、同級元素、屬性讓人好半天都沒(méi)有理出頭緒來(lái)。
這次我們介紹的 JiBX 是處理 XML 的高級 API,同類(lèi)的項目還有 JAXB, Castor, Zeus。使用這類(lèi)高級 API,在處理 XML 的使用,你的 Java 應用中將不再會(huì )有元素和屬性,取而代之的是對象和值域。優(yōu)點(diǎn)顯而易見(jiàn),處理 XML 的難度大大降低,而且更加符合面向對象的編程思想。
一 JiBX 簡(jiǎn)介
JiBX 是一個(gè)綁定 XML 數據到 Java 對象的框架。JiBX 用一個(gè)綁定定義文擋(binding definition document)來(lái)定義 XML 數據與 Java 對象轉換的規則,這個(gè)文擋就是聯(lián)系 XML 數據與 Java 對象之間的橋梁。
這里有必要先介紹兩個(gè)數據綁定術(shù)語(yǔ) marshal 和 unmarshal,marshal 是由 Java 對象生成 XML 文擋,unmarshal 是根據 XML 文擋建立 Java 對象。
使用 JiBX 的過(guò)程分成兩個(gè)過(guò)程,一個(gè)是 binding compiler,另一個(gè)是 binding runtime。binding compiler 是一個(gè)前期準備過(guò)程,包括定義綁定定義文擋,定義與 XML 綁定在一起的 Java 對象,然后編譯。在這個(gè)過(guò)程,JiBX 比其他項目在操作上要簡(jiǎn)單,不用定義 DTD 和 Schema,缺點(diǎn)是需要自己定義 Java 程序。binding runtime 是使用 binding compiler 編譯好的 Java class 處理 XML 數據。
JiBX 也用到了第三方的工具 XPP3 Pull Parser 和 BCEL,在 JiBX 發(fā)布的文件中也包含了這兩個(gè)工具相關(guān)的文件。
二 簡(jiǎn)單范例
按照慣例,還是從最簡(jiǎn)單的例子說(shuō)起。
首先從 JiBX 網(wǎng)站下載 JiBX,當前最新版本是 beta 3。解開(kāi)下載的 zip 文件,里面有一個(gè) lib 目錄,包含了 bcel.jar, jibx-bind.jar, jibx-extras.jar, jibx-run.jar, xpp3.jar 五個(gè) jar 文件。bcel.jar, jibx-bind.jar 只有在 binding compiler 的時(shí)候才用得到。jibx-extras.jar 是一個(gè)可選的工具包,里面有一些測試和驗證的工具類(lèi)。
1.定義一個(gè)我們將要處理 XML 文件,文件名為 data.xml,內容如下:
<customer>
<person>
<cust-num>123456789</cust-num>
<first-name>John</first-name>
<last-name>Smith</last-name>
</person>
<street>12345 Happy Lane</street>
<city>Plunk</city>
<state>WA</state>
<zip>98059</zip>
<phone>888.555.1234</phone>
</customer>這個(gè) XML 文件非常簡(jiǎn)單,共有十個(gè)元素,沒(méi)有屬性。根元素 customer 有 person, street, city, state, zip, phone 六個(gè)子元素。其中元素 person 有 cust-num, first-name, last-name 三個(gè)子元素。
2.接著(zhù)定義兩個(gè) Java 類(lèi) Customer 和 Person,也采用最簡(jiǎn)單的方式,用對象的域值對應元素,內容如下:
public class Customer {
public Person person;
public String street;
public String city;
public String state;
public Integer zip;
public String phone;
}
public class Person {
public int customerNumber;
public String firstName;
public String lastName;
}這個(gè)兩個(gè)類(lèi)沒(méi)有任何方法,夠簡(jiǎn)單吧!或許你已經(jīng)看出來(lái)了,Customer 類(lèi)的七個(gè) field 對應的是 XML 文件中 customer 元素的七個(gè)子元素。Person 類(lèi)的三個(gè) field 對應的是 person 元素的三個(gè)子元素。在 Person 類(lèi)的 field 的名稱(chēng)并不是和 person 元素的子元素名稱(chēng)完全相等,這是遵守 Java 編程規范 field 命名的需要,雖然不相等,但這不重要,可以在綁定定義文擋中把它們一一對應起來(lái)。
3.綁定定義文擋
綁定定義文擋是依據綁定定義規范將 XML 數據和 Java 對象綁定的 XML 文擋。文件名為 binding.xml,內容如下:
<binding>
<mapping name="customer" class="Customer">
<structure name="person" field="person">
<value name="cust-num" field="customerNumber"/>
<value name="first-name" field="firstName"/>
<value style="text" field="lastName"/>
</structure>
<value name="street" field="street"/>
<value name="city" field="city"/>
<value name="state" field="state"/>
<value name="zip" field="zip"/>
<value name="phone" field="phone"/>
</mapping>
</binding>binding.xml 文件中的 name 和 field 屬性分別將 XML 中的元素和 Java 對象中的 field 一一對應并綁定起來(lái)。
<mapping name="customer" class="Customer">mapping 元素的 name 和 class 屬性將 customer 根元素和 Customer 類(lèi)綁定在一起。
<structure name="person" field="person">
public Person person;上面兩行定義了 person 是 Customer 的 field,同時(shí)也把 person 元素和 person 類(lèi)綁定在一起。
4.現在來(lái)看看他們之間的關(guān)系吧,如下圖
圖片來(lái)自 Jibx 官方網(wǎng)站對于最終用戶(hù)來(lái)說(shuō),他們只知道 XML 數據文擋和 Java 類(lèi),而綁定定義文擋是透明的。
5.執行 Binding Compiler 過(guò)程
以下命令是在 Linux 下執行,如果是 Windows 平臺請轉換成相應的命令
#javac Person.java
#javac -classpath . Customer.java
#java -jar lib/jibx-bind.jar binding.xml執行完后,在當前目錄多了四個(gè) class 文件,分別是 Person.class, Customer.class, JiBX_bindingCustomer_access.class, JiBX_bindingFactory.class。
6.執行 binding runtime 過(guò)程
首先定制一個(gè) XML 數據文件 data.xml, 內容如下:
<customer>
<person>
<cust-num>123456789</cust-num>
<first-name>John</first-name>
<last-name>Smith</last-name>
</person>
<street>12345 Happy Lane</street>
<city>Plunk</city>
<state>WA</state>
<zip>98059</zip>
<phone>888.555.1234</phone>
</customer>接著(zhù)寫(xiě)一個(gè)簡(jiǎn)單的讀取 data.xml 測試程序 Test.java,內容如下:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import org.jibx.runtime.JiBXException;
import org.jibx.runtime.IBindingFactory;
import org.jibx.runtime.BindingDirectory;
import org.jibx.runtime.IUnmarshallingContext;
class Test {
public static void main(String[] args) {
try{
IBindingFactory bfact = BindingDirectory.getFactory(Customer.class);
IUnmarshallingContext uctx = bfact.createUnmarshallingContext();
Customer customer = (Customer)uctx.unmarshalDocument(new FileInputStream("data.xml"), null);
Person person = customer.person;
System.out.println("cust-num:" + person.customerNumber);
System.out.println("first-name:" + person.firstName);
System.out.println("last-name:" + person.lastName);
System.out.println("street:" + customer.street);
}catch(FileNotFoundException e){
System.out.println(e.toString());
}catch(JiBXException e){
System.out.println(e.toString());
}
}
}編譯并運行這個(gè)測試程序
#javac -classpath .:lib/jibx-run.jar Test.java
#java -cp .:lib/jibx-run.jar:lib/xpp3.jar Test程序運行的結果是
cust-num:123456789
first-name:John
last-name:Smith
street:12345 Happy Lane三 總結
總的來(lái)說(shuō),JiBX 就這么簡(jiǎn)單,不過(guò) JiBX 還有一稍微復雜一點(diǎn)的應用,本文沒(méi)有介紹,感興趣的朋友可以繼續研究下去。如果你有什么問(wèn)題可以直接到我們的論壇 http://www.sentom.net/forum 提出,也非常歡迎把你的經(jīng)驗給大家分享。
原作者:王恩建
來(lái) 源:http://www.sentom.net
共有1760位讀者閱讀過(guò)此文
聯(lián)系客服