O/X Mapper 是什麼? java
Spring 3.0 的一個新特性是 O/X Mapper。O/X 映射器這個概念並不新鮮,O 表明 Object,X 表明 XML。它的目的是在 Java 對象(幾乎老是一個 plain old Java object,或簡寫爲 POJO)和 XML 文檔之間來回轉換。node
例 如,您可能有一個帶有幾個屬性的簡單 bean,且您的業務須要將那個 Java 對象轉換爲一個 XML 文檔。Spring 的 O/X Mapper 可以爲您解決那個問題。若是反過來,您須要將一個 XML 文檔轉換爲一個簡單 Java bean,Spring 的 O/X Mapper 也能勝任。spring
有一點須要注意:Spring O/X Mapper 只是定義由流行的第三方框架實現的統一的界面。要利用 Spring 的 O/X 功能,您須要一個在 Java 對象和 XML 之間來回轉換的實用程序。Castor 就是這樣一個流行的第三方工具,本文將使用這個工具。其餘這樣的工具包括 XMLBeans、Java Architecture for XML Binding (JAXB)、JiBX 和 XStream。express
編組和解組app
進行 O/X 映射時,您常常會看到編組(marshalling)和解組(unmarshalling) 這兩個術語。框架
編組 指將 Java bean 轉換成 XML 文檔的過程,這意味着 Java bean 的全部字段和字段值都將做爲 XML 元素或屬性填充到 XML 文件中。有時,編組也稱爲序列化(serializing)。工具
如您所料,解組 是與編組徹底相反的過程,即將 XML 文檔轉換爲 Java bean,這意味着 XML 文檔的全部元素或屬性都做爲 Java 字段填充到 Java bean 中。有時,解組也稱爲反序列化(deserializing)。
測試
使用 Spring 的 O/X Mapper 的好處this
使 用 Spring 的 O/X Mapper 的一個最直接的好處是能夠經過利用 Spring 框架的其餘特性簡化配置。Spring 的 bean 庫支持將實例化的 O/X 編組器注入(即前面提到過的 「依賴項注入」)使用那些編組器的對象。重申一遍,這將加快應用程序開發和部署。編碼
遵循堅實的面向對象的設計實踐,Spring O/X 框架只定義兩個接口:Marshaller 和 Unmarshaller,它們用於執行 O/X 功能,這是使用這個框架的另外一個重大好處。這些接口的實現徹底對獨立開發人員開放,開發人員能夠輕鬆切換它們而無需修改代碼。例如,若是您一開始使用 Castor 進行 O/X 轉換,但後來發現它缺少您須要的某個功能,這時您能夠切換到 XMLBeans 而無需任何代碼更改。惟一須要作的就是更改 Spring 配置文件以使用新的 O/X 框架。
使用 Spring 的 O/X Mapper 的另外一個好處是統一的異常層次結構。Spring 框架遵循使用它的數據訪問模塊創建的模式,方法是將原始異常對象包裝到 Spring 自身專爲 O/X Mapper 創建的運行時異常中。因爲第三方提供商拋出的原始異常被包裝到 Spring 運行時異常中,您可以查明出現異常的根本緣由。您也沒必要費心修改代碼以捕獲異常,由於異常已包裝到一個運行時異常中。如下幾個運行時異常擴展了基礎異常 XMLMappingException:GenericMarshallingFailureException、 ValidationFailureException、MarshallingFailureException 和 UnmarshallingFailureException。
一個簡單的演示
現 在您已經瞭解了 Spring 的 O/X Mapper 的背景和基礎知識,能夠檢驗它的使用方法了。在本文中,您首先建立一個簡單的 Spring 應用程序,該程序獨立於任何 Java Enterprise 依賴項。而後,您建立一個簡單的 Java 類,它訪問 Spring 的配置文件來實例化該類並注入 O/X 依賴項。
編碼
首先應該注意 Spring 配置文件。清單 1 是應用程序用於執行編組和解組操做的配置文件。注意,這個文件必須 在運行時位於類路徑中。
清單 1. 配置文件
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id="oxmExample" class="com.xyz.OXMExample"> <property name="marshaller" ref="castorMarshaller" /> <property name="unmarshaller" ref="castorMarshaller" /> </bean> <bean id="castorMarshaller" class="org.springframework.oxm.castor.CastorMarshaller"> <property name="mappingLocation" value="classpath:mapping.xml" /> </bean> </beans>
如 您所見,這個配置文件只定義了兩個 bean,這是爲了簡便起見。第一個 bean 是用於執行演示的類:com.xyz.OXMExample。與該類關聯的兩個屬性使用依賴項注入,它們都使用 castorMarshaller bean 的一個實例注入。這是在 Spring 框架中定義 bean 的標準方法,經驗豐富的 Spring 開發人員很快就會意識到這一點。另 一個 bean 是 castorMarshaller bean 自己,它org.springframework.oxm.castor.CastorMarshaller 的一個實例,org.springframework.oxm.castor.CastorMarshaller 主要用於包裝 Castor 框架。如前所述,使用 Spring 的 O/X 功能須要使用一個第三方 O/X 框架。在本例中,這個第三方產品是 Castor。還要注意,有一個屬性使用 castorMarshaller 定義,那是用於在 Java bean 和 XML 輸出之間來回映射的映射文件。這個文件稱爲 mapping.xml,它必須 在運行時位於類路徑中。我將稍後解釋 mapping.xml 文件的內容。
清單 2 實際執行 O/X 映射器的代碼的部分清單。如您所見,它是一個簡單的 Java 類。
清單 2. OXMExample 類(節選)
public class OXMExample { private static final String FILE_NAME = "simplebean.xml"; private SimpleBean simpleBean; private Marshaller marshaller; private Unmarshaller unmarshaller; public void setMarshaller(Marshaller marshaller) { this.marshaller = marshaller; } public void setUnmarshaller(Unmarshaller unmarshaller) { this.unmarshaller = unmarshaller; } public void saveSimpleBean() throws IOException { FileOutputStream os = null; try { os = new FileOutputStream(FILE_NAME); this.marshaller.marshal(simpleBean, new StreamResult(os)); } finally { if (os != null) { os.close(); } } } public void loadSimpleBean() throws IOException { FileInputStream is = null; try { is = new FileInputStream(FILE_NAME); this.simpleBean = (SimpleBean) this.unmarshaller.unmarshal(new StreamSource(is)); } finally { if (is != null) { is.close(); } } } public static void main(String[] args) throws IOException { ApplicationContext appContext = new ClassPathXmlApplicationContext("applicationContext.xml"); OXMExample ex = (OXMExample) appContext.getBean("oxmExample"); ex.go(); } private void go() throws IOException { simpleBean = getSimpleBean(); saveSimpleBean(); loadSimpleBean(); System.out.println("name: " + simpleBean.getName()); System.out.println("job description: " + simpleBean.getJobDescription()); System.out.println("age: " + simpleBean.getAge()); System.out.println("executive: " + simpleBean.isExecutive()); } private SimpleBean getSimpleBean() { SimpleBean simpleBean = new SimpleBean(); simpleBean.setAge(35); simpleBean.setExecutive(false); simpleBean.setJobDescription("Janitor"); simpleBean.setName("Mister Jones"); return simpleBean; } }
要解釋 清單 2,必須首先介紹 main 方法,由於該方法將先執行。而後再接着介紹清單 2。
首先,在 main 方法中,您的代碼捕獲 Spring 應用程序的上下文,就是您在 清單 1 中看到的配置文件。這個文件必須在類路徑中,不然運行代碼將產生一個異常。
當 您得到應用程序上下文時,OXMExample 的一個實例從該配置文件中提供的定義建立。注意,這個 bean 在代碼中的名稱(oxmExample)與配置文件中定義的名稱(見清單 1)一致。建立 OXMExample 的一個實例後,調用 go() 方法。這有點反常,由於 Spring 框架實例化一個已經從命令行運行的對象,但那只是爲了實現演示目的而進行的簡化。
go() 方法在打印結果數據前完成 3 個任務:
1. 建立 SimpleBean 的一個實例。
2. 編組該實例。
3. 解組從編組建立的 XML 文檔。
您 使用 getSimpleBean() 方法實例化一個包含一個虛擬員工的信息的 SimpleBean 對象。這個信息包含年齡(一個整數)、工做描述(一個字符串)、姓名(一個字符串)和該員工是不是執行官(一個布爾型)。您使用測試數據和返回調用者的返 回對象(在本例中爲 go() 方法)填充字段。您在編組發生時將這個 bean 寫入一個 XML 文件,在解組發生時讀取那個 XML 文件的內容。
saveSimpleBean() 方法執行編組。首先,您得到一個指向 simplebean.xml 的對象,而後,您使用編組器對象(經過 Spring 的依賴項注入實例化)調用 marshal 方法。這個方法須要兩個參數:
要被編組的對象(本例中爲 SimpleBean 實例)
一個 StreamResult 對象,它基本上表示一個 XML 輸出抽象
loadSimpleBean() 方法執行解組。首先,您獲取一個指向 simplebean.xml 的 FileInputStream 對象,而後,您使用解組器對象(經過 Spring 的依賴項注入實例化)調用 unmarshal 方法。惟一須要的參數是一個包裝 FileInputStream 對象的 StreamSource 對象。注意,解組將建立一個泛型對象,所以您必須將其顯式設置爲 SimpleBean 類型。
即便這個類和 Spring 配置文件已經就緒,您也尚未準備好運行這段代碼。還記得 清單 1 中的映射文件嗎?您還須要定義那個映射文件。定義代碼如 清單 3 所示,並且,再說一遍,它也必須在運行時位於類路徑中。
清單 3. mapping.xml 文件
<mapping> <class name="com.xyz.SimpleBean"> <map-to xml="simplebean"/> <field name="age" type="integer"> <bind-xml name="age" node="element"/> </field> <field name="executive" type="boolean"> <bind-xml name="is-executive" node="element"/> </field> <field name="jobDescription" type="string"> <bind-xml name="job" node="element"/> </field> <field name="name" type="string"> <bind-xml name="name" node="element"/> </field> </class> </mapping>
清單 3 中的映射文件特定於 O/X 映射的 Castor 實現。第一個元素(class)定義要映射到一個 XML 輸出的類。您必須指定完整路徑。
map-to 元素提供 XML 文件的根元素的名稱。這很重要,由於 XML 規範規定,每一個 XML 文件必須有一個根元素。
每 個 field 元素都將被映射到 SimpleBean 類中的一個特定字段。每一個 field 元素的 bind-xml 子元素用於指定關於該字段的特定於 XML 的信息,如對應的 XML 元素的名稱,每一個字段的值應該是一個元素值仍是一個屬性值。如您所見,在本例中,全部值都是元素值。
測試
儘管代碼已經編寫完成,但在執行這個應用程序以前,您必須處理一些依賴項。
特定於 Spring 的依賴項有:
org.springframework.asm-3.0.0.M4.jar
org.springframework.beans-3.0.0.M4.jar
org.springframework.context-3.0.0.M4.jar
org.springframework.core-3.0.0.M4.jar
org.springframework.expression-3.0.0.M4.jar
org.springframework.oxm-3.0.0.M4.jar
特定於 Castor 的依賴項有:
castor-1.3-core.jar
castor-1.3-xml.jar
您還須要 commons-logging-1.1.1.jar 和 log4j-1.2.15.jar,由於 Spring 框架須要它們。
所 有這些 Java Archive (JAR) 文件必須在運行時位於類路徑中。若是您在沒有這些依賴項的狀況下試圖運行代碼,您極可能會收到一個異常,指出某個類沒有找到。若是遇到這種狀況,只需雙擊 您的類路徑,確保全部的必要依賴項已就緒。事實上,要成功編譯這段代碼,您須要大部分 JAR 文件。要了解關於獲取這些 JAR 文件的信息,請參見本文末尾的 參考資料。
您 可使用您鍾愛的 IDE 或只是使用命令行來運行 OXMExample.class。要從命令行運行,只需從您的工做目錄輸入 java -cp [classpath] OXMExample,這裏的 [classpath] 是指向剛纔提到的全部依賴項(JAR 文件和配置文件)的類路徑。
首次運行該程序後,一個名爲 simplebean.xml 的新文件將出如今您的工做目錄中。該文件的內容應該如 清單 4 所示。
清單 4. simplebean.xml 文件
<?xml version="1.0" encoding="UTF-8"?> <simplebean> <age>35</age> <is-executive>false</is-executive> <job>Janitor</job> <name>Mister Jones</name> </simplebean>
清單 4 顯示了來自應用程序的編組端的輸出,而 清單 5 則顯示來自應用程序的解組端的結果,這些結果將在您的控制檯中顯示。
清單 5. 解組輸出
name: Mister Jones job description: Janitor age: 35 executive: false |
如今,您已經成功地完成了您的首次 Spring O/X 映射測試。祝賀您!
如今最好作開發人員應該作的工做:修改代碼。向類添加字段並將它們映射到 XML 文件。刪除一些字段並將它們從 XML 文件中移除。參考 Castor 文檔,嘗試一些更復雜的工做,好比嵌套元素。您能夠爲所欲爲地嘗試各類可能性。
結束語
Spring 的 O/X 映射接口是 Spring 框架的強大特性。藉助它,您不只能夠將 XML 文檔轉換爲 Java 對象,還能夠將 Java 對象轉換爲 XML 文檔。
它 利用 Spring 的一個關鍵優點:依賴項注入。經過結合使用依賴項注入和 Spring 的 O/X Mapper,您能夠輕鬆開發一個解決方案,該方案可使用任一 O/X 實現,好比 Castor、XBeans、JiBX、JAXB 和 XStream。因爲各個特定實現是 Spring 強大的 Inversion of Control 容器的一部分,開發人員能夠在多個特定 O/X 實現之間輕鬆切換而無需修改代碼。
Spring 的 O/X Mapper 還向開發人員提供一個統一的異常層次結構,這意味着無論您使用哪一個第三方實現,拋出的運行時異常都是相同的。再強調一次,這將有利於在多個 O/X 供應商之間切換。
在 Java 開發社區中,提供 XML 支持的 Java 應用程序很是熱門而且 Spring 框架被普遍使用,所以 Spring 的 O/X Mapper 將受到全世界 Java 應用程序開發人員的歡迎。