Introduction to JAXB (1)

從Hearbeat說起

公司的運營部門要求所有上線的component有個鏈接,進行heartbeat檢測。

要求如下:

  1. 提供一個http url
  2. 這個http url 返回xml來顯示server的狀態,格式如下

heartbeat需要check哪些內容(db/io/thread/cpu/memory/file handler...),這裏不作討論。我看過的code中,有以下實現:

  • 打開一個socket端口(非web app),如果系統自檢 ok, 返回一個OK的xml字符串。如果自檢失敗,返回fail的xml字符串。

  • 定義一個servlet(web app),其他同上。
  • 爲heartbeat定義一個wsdl(web app, deploy in axis2 aar ), 提供一個heartbeat service,比如:

http://host/app/UserService (domain service) 
http://host/app/HeartbeatService (heartbeat service)

  • 使用axis2的RawXMLINOutMessageReceiver或者AbstractInOutMessageReceiver(web app, deploy in axis2 aar),定義一個POJOs的service, 返回OMElement(可以從xml轉換得到)。本質和3相同,不過是少了wsdl

 

按照生成xml的方法,上面四種方式歸結爲3種

  1. raw string
  2. 定義xsd
  3. 使用DOM Tree (OMElement)。使用DOM Tree給人的感覺和raw string沒啥區別。

這裏就出現了JAXB的第一個應用場景: 需要生成xml,xml相對簡單:定義xsd有大材小用之嫌,代碼中字符串拼接又太ugly。

什麼是JAXB

Java Architecture for XML Binding(JAXB) 是一種OX(object <-> xml mapping)工具。主要提供了兩個功能:將 java對象編碼序列化(marshal)成xml,或者反之,從xml反序列化到java對象。一圖以蔽之:

  • xml schema 與 classes(interfaces) 之間的相互轉換(爲下面的轉換做鋪墊)
  • xml document 和 instance object 之間的相互轉換

xml是比java,c++, python...等編程語言更通用的描述語言,從語言相互翻譯的角度而言,上面兩種映射天然如此。

 

序列化任意java對象

回到本文開頭heartbeat xml生成的問題,

  • 首先定義HeartBeat類,包含status。selfCheck方法檢測server的各種狀態,這裏僅僅是sample stub code,直接返回一個HeartBeat

 

  • 使用JAXB將HeartBeat實例對象marshal成xml

 

  • 生成的xml如下

 

說明:

Status被定義成static inner class而不是inner class,否則會報錯is a non-static inner class, and JAXB can’t handle those.

JAXBElement中Qname的local part爲admin,因爲xml的root elment從admin開始

 


在上面的例子中,Heartbeat類定義上未加任何的annotation,就直接被JAXB marshal。理論上,我們可以仿照上一篇A generic JAXB marshal/unmarshal XmlType中的泛型方法定義,將marshal方法定義成一個可marhal任意java對象的通用方法。不過在實際中,我們很少直接handle未加任何jaxb annotation的對象,主要有循環引用,內部類等問題。

 

上面的例子可以看出jaxb相當簡單易用(點此從一個實例看jaxb的強大),秉承JDK API的一貫風格。

XJC:schema -> java

如果遵循contract first的原則,在解決與xml相關的問題時,schema first.

  • 首先定義heartbeat的schema如下(由xml->xsd在線工具得到):

  • 使用xjc(jdk工具,與java/javac在同一目錄,在CMD命令窗口可直接使用),生成java類:xjc heartbeat.xsd

Admin

 

 

ObjectFactory


 

  • 使用jaxb,將admin marshal。比前面少了兩行new JAXBElement對象的代碼

 

 

class定義中使用的Annotation和xml schema定義一一對應,說明如下:

 

@XmlRootElement(name = "admin")


//xml 文檔根節點

<xsd:element name="admin">

@XmlAccessorType(XmlAccessType.FIELD)

@XmlType(name = "", propOrder = {

"status"

})

@XmlElement(required = true)

protected List<Admin.Status> status;


//nested 的complexType,所以XmlType的name爲空;有Order indicator 

sequence,所以有propOrder來指定序列化順序

//maxOccurs爲unbounded,所以status定義爲List,默認minOccurs爲1,所以添加了required = true

 

//XmlAccessorType 表明了哪些field需要被序列化。


 

 

<xsd:complexType>
     <xsd:sequence>

          <xsd:element maxOccurs="unbounded" name="status">

@XmlAccessorType(XmlAccessType.FIELD)

@XmlType(name = "", propOrder = {

"name",

"value"

})

 

//同上

             <xsd:complexType>

               <xsd:sequence>

                  <xsd:element name="name" type="xsd:int" />

                  <xsd:element name="value" type="xsd:int" />

               </xsd:sequence>

             </xsd:complexType>

          </xsd:element>

    </xsd:sequence>

</xsd:complexType>

 

</xsd:element>

schemagen:java -> schema

如果你習慣先寫java class,或者已經有很多寫好的java code(有沒有jaxb annotation都成)。schemagen(同xjc,jdk工具)是幫助你快速定義schema的不二選擇。

 

對上面生成的Admin.java使用schemagen(schemagen Admin.java),生成的schema和前面的定義一模一樣

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章