spring oxm入門(包含demo)


O/X Mapper 是什么?  

Spring 3.0 的一個新特性是 O/X Mapper。O/X 映射器這個概念並不新鮮,O 代表 Object,X 代表 XML。它的目的是在 Java 對象(幾乎總是一個 plain old Java object,或簡寫為 POJO)和 XML 文檔之間來回轉換。

例 如,您可能有一個帶有幾個屬性的簡單 bean,且您的業務需要將那個 Java 對象轉換為一個 XML 文檔。Spring 的 O/X Mapper 能夠為您解決那個問題。如果反過來,您需要將一個 XML 文檔轉換為一個簡單 Java bean,Spring 的 O/X Mapper 也能勝任。

有一點需要注意:Spring O/X Mapper 只是定義由流行的第三方框架實現的統一的界面。要利用 Spring 的 O/X 功能,您需要一個在 Java 對象和 XML 之間來回轉換的實用程序。Castor 就是這樣一個流行的第三方工具,本文將使用這個工具。其他這樣的工具包括 XMLBeans、Java Architecture for XML Binding (JAXB)、JiBX 和 XStream。

編組和解組

進行 O/X 映射時,您經常會看到編組(marshalling)和解組(unmarshalling) 這兩個術語。

編組 指將 Java bean 轉換成 XML 文檔的過程,這意味着 Java bean 的所有字段和字段值都將作為 XML 元素或屬性填充到 XML 文件中。有時,編組也稱為序列化(serializing)。

如您所料,解組 是與編組完全相反的過程,即將 XML 文檔轉換為 Java bean,這意味着 XML 文檔的所有元素或屬性都作為 Java 字段填充到 Java bean 中。有時,解組也稱為反序列化(deserializing)。

使用 Spring 的 O/X Mapper 的好處

使 用 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. 配置文件

?
1
2
3
4
5
6
7
8
9
10
11
12
13
< 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 類(節選)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
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 文件

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
< 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 文件

?
1
2
3
4
5
6
7
<? 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 應用程序開發人員的歡迎。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM