DIV CSS 佈局教程網

 DIV+CSS佈局教程網 >> 網頁腳本 >> XML學習教程 >> XML詳解 >> 實用數據綁定: 考察 JAXB,第 1 部分:往返和 XML 到 Java 的轉換
實用數據綁定: 考察 JAXB,第 1 部分:往返和 XML 到 Java 的轉換
編輯:XML詳解     

 在深入數據綁定的細節,尤其是探討如何將數據綁定工具包用於一般的編程問題之前,您需要選擇使用的數據綁定工具包。我的一般原則是您應該自行挑選軟件,因為每個人的編程需求無疑都是唯一的。也就是說,程序員做出這些決策所用的信息是普遍適用的。本文中,我將根據這些普遍的原則分析 JAXB,並幫助確定 JAXB 是否適合您的數據綁定需求。

  簡述

不過在展開 JAXB 的討論之前,我要簡要地回顧一下本系列 上一篇文章中所提到的概念。其中的重要定義有:

  解組:把 XML 數據轉化成 Java 類(或者多個類)的過程。

  編組:把 Java 數據轉化成 XML 文檔的過程(恰恰與解組相反)。

  語義等價:基於 XML 規則的相等。即使兩個文檔 看起來不同,但在語義上可能是等價的,參見上一篇文章中的例子。

  往返:從 XML 文檔到 Java 代碼然後再回到 XML 的整個過程。有效的往返保證輸入和輸出文檔是相同的(語義等價)。

  本文中將不那麼嚴格地使用這些術語,一定要真正掌握每個概念的含義。

  還應該明白,本文以及後面的幾篇文章中,重點不一定是討論基本的功能,而使這種功能的實現。煤中數據綁定工具包都能編組和解組數據。但是許多工具包不那麼嚴格地執行這項任務,結果危害了往返的語義等價性。實現中的瑕疵(或者實現的功能不完整)是本系列中開始幾篇文章的重點,因此我要用幾篇文章來說明工具包的基本用法就不奇怪了,如果不知道它是否 真正有效, 使用一個工具包又有什麼意義呢?

 最後,我假設您已經安裝並運行了 JAXB。您可以在 developerWorks上找到詳細描述安裝過程的大量文章,而且有了新的 Sun Java Web Services Developer Toolkit,安裝非常簡單。安裝好工具包並設置正確的類路徑,就萬事俱備了。

  生成類

使用 JAXB 進行之前,首先要生成表示 XML 數據的 Java 類。這些例子中將使用一個非常簡單的 XML 文檔,如清單 1 所示。這是一份吉他的簡單列表,吉他是我的愛好之一。

  清單 1. 簡單的 XML 文檔:吉他列表

<guitars> 
 <guitar id="10021"> 
  <builder luthIEr="true">Ryan</builder> 
  <model>Mission Grand Concert</model> 
  <back-sides>Brazilian Rosewood</back-sides> 
  <top>Adirondack Spruce</top> 
  <notes> 
   <![CDATA[ 
    Just unbelIEvable...  this guitar has all the tone & 
    resonance you could ever want. I mean, <<WOW!!!>> This 
    is a lifetime guitar. 
   ]]> 
  </notes> 
 </guitar> 
 <guitar id="0923"> 
  <builder smallShop="true">Bourgeois</builder> 
  <model>OMC</model> 
  <back-sides>Bubinga</back-sides> 
  <top>Adirondack Spruce</top> 
 </guitar> 
 <guitar id="11091"> 
  <builder>Martin & Company</builder> 
  <model>OM-28VR</model> 
  <back-sides>Indian Rosewood</back-sides> 
  <top bearclaw="true">Sitka Spruce</top> 
  <notes>It's certainly true that Martin isn't the only game in town anymore. 
      Still, the OM-28VR is one of their best models...   and this one 
      has some fabulous bearclaw to boot.       Nice specimen of a 
      still-important guitar manufacturer. 
  </notes> 
 </guitar> 
</guitars> 

使用 JAXB 時還需要一個 XML Schema 以生成類和數據結構。 清單 1的 XML Schema 如清單 2 所示。

  清單 2. 清單 1 的 XML Schema

<?XML version="1.0" encoding="UTF-8"?> 
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
      elementFormDefault="qualifIEd"> 
 <xs:element name="back-sides" type="xs:string"/> 
 <xs:element name="builder"> 
  <xs:complexType> 
   <xs:simpleContent> 
    <xs:extension base="xs:string"> 
     <xs:attribute name="luthIEr" default="false"> 
      <xs:simpleType> 
       <xs:restriction base="xs:NMTOKEN"> 
        <xs:enumeration value="true"/> 
        <xs:enumeration value="false"/> 
       </xs:restriction> 
      </xs:simpleType> 
     </xs:attribute> 
     <xs:attribute name="smallShop" default="false"> 
      <xs:simpleType> 
       <xs:restriction base="xs:NMTOKEN"> 
        <xs:enumeration value="true"/> 
        <xs:enumeration value="false"/> 
       </xs:restriction> 
      </xs:simpleType> 
     </xs:attribute> 
    </xs:extension> 
   </xs:simpleContent> 
  </xs:complexType> 
 </xs:element> 
 <xs:element name="guitar"> 
  <xs:complexType> 
   <xs:sequence> 
    <xs:element ref="builder"/> 
    <xs:element ref="model"/> 
    <xs:element ref="back-sides"/> 
    <xs:element ref="top"/> 
    <xs:element ref="notes" minOccurs="0"/> 
   </xs:sequence> 
   <xs:attribute name="id" type="xs:string" use="required"/> 
  </xs:complexType> 
 </xs:element> 
 <xs:element name="guitars"> 
  <xs:complexType> 
   <xs:sequence> 
    <xs:element ref="guitar" maxOccurs="unbounded"/> 
   </xs:sequence> 
  </xs:complexType> 
 </xs:element> 
 <xs:element name="model" type="xs:string"/> 
 <xs:element name="notes" type="xs:string"/> 
 <xs:element name="top"> 
  <xs:complexType> 
   <xs:simpleContent> 
    <xs:extension base="xs:string"> 
     <xs:attribute name="bearclaw" default="false"> 
      <xs:simpleType> 
       <xs:restriction base="xs:NMTOKEN"> 
        <xs:enumeration value="true"/> 
        <xs:enumeration value="false"/> 
       </xs:restriction> 
      </xs:simpleType> 
     </xs:attribute> 
    </xs:extension> 
   </xs:simpleContent> 
  </xs:complexType> 
 </xs:element> 
</xs:schema> 

基本步驟

准備好了 XML 和 XML Schema,生成 JAXB 類就很簡單了。確認已設置好命令行和環境,然後輸入以下命令:

xjc -p com.ibm.dw guitars.xsd -d src 

  一定要在和 guitars.xsd文件相同的目錄中執行上述命令,並且在工作目錄中建立一個 src目錄。如果沒有按這些步驟操作,就會出現某種 Java.io.IOException 錯誤。否則應該能看到一長串的輸出結果,如清單 3 所示。

  清單 3. JAXB 類生成的輸出結果

C:\developerworks>xjc -p com.ibm.dw guitars.xsd -d src 
parsing a schema... 
compiling a schema... 
com\ibm\dw\impl\runtime\MSVValidator.Java 
com\ibm\dw\impl\runtime\SAXUnmarshallerHandlerImpl.Java 
com\ibm\dw\impl\runtime\ErrorHandlerAdaptor.Java 
com\ibm\dw\impl\runtime\AbstractUnmarshallingEventHandlerImpl.Java 
com\ibm\dw\impl\runtime\UnmarshallableObject.Java 
com\ibm\dw\impl\runtime\SAXMarshaller.Java 
com\ibm\dw\impl\runtime\XMLSerializer.Java 
com\ibm\dw\impl\runtime\ContentHandlerAdaptor.Java 
com\ibm\dw\impl\runtime\UnmarshallingEventHandlerAdaptor.Java 
com\ibm\dw\impl\runtime\SAXUnmarshallerHandler.Java 
com\ibm\dw\impl\runtime\ValidatorImpl.Java 
com\ibm\dw\impl\runtime\ValidatableObject.Java 
com\ibm\dw\impl\runtime\UnmarshallerImpl.Java 
com\ibm\dw\impl\runtime\NamespaceContext2.Java 
com\ibm\dw\impl\runtime\Discarder.Java 
com\ibm\dw\impl\runtime\NamespaceContextImpl.Java 
com\ibm\dw\impl\runtime\ValidatingUnmarshaller.Java 
com\ibm\dw\impl\runtime\UnmarshallingContext.Java 
com\ibm\dw\impl\runtime\GrammarInfoImpl.Java 
com\ibm\dw\impl\runtime\ValidationContext.Java 

實在是有點太多了--注意,即使對於一個相當簡單的 XML Schema,JAXB 也創建了 大量的類。

  對往返的影響

現在我已經介紹了基本的步驟,下面將實際分析一下其中到底發生了什麼。不必浪費時間回顧 JAXB 的基礎(其他文章已經做了很好的介紹),對於每個元素都有兩個源文件,一個文件和元素同名(比如,Guitar.java),另一個則在元素名後面加上 “Type”(如 GuitarType.Java)。這兩個文件都是接口,類的實現在子目錄 impl 下。這樣就生成了很多類--我認為有點太過分了。

  但真正有意思的是這些類本身。要知道數據綁定實現的主要問題之一是往返--即從 XML 到 Java 代碼再返回到 XML 的過程中數據不會發生不可預料的變化的能力。換句話說,進去的是什麼出來的就是什麼。在目前,您還沒有准備好通過解組-編組循環測試輸出的結果(盡管以後要這樣做),首先來分析源代碼中可能存在的潛在問題。

  第一個問題出現在任何數據綁定軟件包通常都會出問題的地方:類型化。即使有 XML Schema 的幫助,XML 也不一定能和 Java 類型很好的匹配。這通常意味著要損失一些數據類型信息,有可能摻入非法的數據。有時候問題出在 XML Schema 中,有時候則是因為 XML 到 Java 映射的局限性,必須仔細觀察。源代碼中發現的一個此類問題是 top 元素的表示。注意清單 4 中粗體顯示的那一行,這是 TopType 類的源代碼。

  清單 4. TopType.Java 的源代碼

package com.ibm.dw; 
public interface TopType { 
  Java.lang.String getValue(); 
  void setValue(Java.lang.String value); 
      Java.lang.String getBearclaw(); 
  void setBearclaw(Java.lang.String value); 
} 
         

回頭再看一看源文檔及其 XML Schema,很明顯 bearclaw 屬性的值應該是“true”或“false”。不幸的是,JAXB 沒有發現這一點並使用布爾數據類型, TopType 類的這個屬性可以接受任何字符串值。結果可能造成錯誤的數據。最終可能出現“True”、“true”、“tRUe”或者任何其他變化形式,而令使用 XML 的應用程序舉止失措。換句話說,您碰到了必須解決的一個問題域。

  這類問題可能有以下不同的解決辦法:

  手工編輯 TopType 類的源代碼,只接受布爾值。

  向 TopType 方法中手工添加異常處理代碼,保證只能提供可以轉化成布爾值的字符串。

  在 XML Schema 中創建表達布爾數據類型的新類型。

  前兩種選擇非常明顯。第三種選擇也很簡單,盡管 W3C 那幫人實際上應該把這一條放在規范中說明。清單 5 給出了一個簡單的布爾類型定義:

  清單 5. 模式中的布爾類型

<xsd:simpleType name="xsd:boolean"> 
 <xsd:restriction base="xsd:string"> 
  <xsd:enumeration value="true"/> 
  <xsd:enumeration value="True"/> 
  <xsd:enumeration value="TRUE"/> 
  <xsd:enumeration value="false"/> 
  <xsd:enumeration value="False"/> 
  <xsd:enumeration value="FALSE"/> 
 </xsd:restriction> 
</xsd:simpleType> 

  看起來不錯,是吧?但問題是它還不能解決這個問題。JAXB 根據 XML Schema 中 xsd:string 構造的用法,仍然會生成接受字符串參數的類。

在您准備告訴我這不成為一個問題之前,先讓我說明 JAXB 通過 什麼來保護您的數據。當從 Java 類編組回到 XML 時,將調用根據 XML Schema(和限制性的類型,如 清單 2和 清單 5所示)生成的驗證方法。換句話說,如果您為 bearclaw 屬性提供了一個值“foobar”,它就會被找出來。不過像“TRUe”、“fAlSe”和“tRue”這樣的值--當然也不想要這種結果--在驗證過程中也會被找出來。現在就需要使用 清單 5中詳細定義的類型, 還要注意“true”和“false”這兩個詞因為大小寫帶來的變化。這種繁雜的工作看起來意義不大。正是這類問題使得往返非常復雜,真正實現要比說起來困難得多。這也 恰恰是在選擇和使用數據綁定軟件包時應該考慮到的那類問題。

  更加需要關注的是,至少對我而言,這樣可能造成超出單次往返過程的問題。要知道錯誤檢查只有在編組時進行,這意味著只要還在內存中,錯誤數據就可以自由地存在於這些成員變量之中等待編組。另外, 任何具有有限值集的性質都存在這種問題,而不僅僅是布爾值。但其中最值得注意的問題是,有時候 XML 文檔被讀入、處理然後供其他應用程序使用,而不是被編組回到 XML。因此所有的應用程序都有可能在這些字段中插入錯誤的數據,而其他任何使用數據的應用程序都會得到那個錯誤數據。除非希望每次訪問信息時都編組類,否則這個問題就確實存在。順便說一句,這些問題表明數據綁定相對而言還不夠成熟,而不僅僅是 JAXB。

  我該怎麼做?

那麼您能做什麼呢?首先要堅持閱讀這些文章。我將詳細分析 JAXB,後面還將探討 Castor,嘗試標志出那些需要注意的地方。不知道問題的關鍵在哪裡,就不能編寫防彈代碼和錯誤檢查代碼;這正是本文以及後面幾篇文章的核心。更重要的是,要認識到即使最好的數據綁定軟件包,也需要一兩個很棒的程序員增加另外的保護措施,才能使其正確地運行。

  最後還要記住,數據綁定並不總是魔法子彈。我並不想打消你們對數據綁定的興趣,恰恰相反,我認為它是一種了不起的應用程序。但是有時候一個簡單的 SAX 程序或者 DOM 樹就能提供需要的全部功能,就不需要再引入數據綁定項目的復雜性了。在以後的專欄中,我將分析使用數據綁定的最佳時機,什麼時候使用 SAX 和 DOM 更有效,並通過大量的例子幫助您作出決策。

  結束語

顯然這裡關於 JAXB 的分析還不夠完全,但是您已經看到了研究數據綁定軟件包時有價值的分析方法。選擇一個數據綁定軟件包要比選擇喜歡的網站和單擊鏈接復雜得多,要保證選擇的應用程序能夠正確處理像往返這樣的問題。

  JAXB 仍然不夠成熟,仍然是一種非常新的技術的較早主要版本。還要記住 JAXB 以前的幾個版本基本上已經廢棄了(還記得當時 JAXB 只能使用 DTD 嗎?它現在只能使用 XSD),因此 1.x 版是對這類問題真正的 第一次嘗試。並不說不應使用 JAXB,只是說必須小心謹慎。

  下一篇文章,我將從類生成轉移到解組和編組,並說明它是如何工作的。我還將鑽研像空格、CDATA 節以及許多其他問題的處理。請繼續堅持,您將看到更多的代碼、更多的細節和更多的樂趣。下一次網上見!








XML學習教程| jQuery入門知識| AJAX入門| Dreamweaver教程| Fireworks入門知識| SEO技巧| SEO優化集錦|
Copyright © DIV+CSS佈局教程網 All Rights Reserved