<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆 - 3, 文章 - 152, 評論 - 17, 引用 - 0
    數據加載中……

    從 XML 到 Java 代碼的數據綁定,系列之一(共四部分)

    Brett McLaughlin
    Enhydra 戰略家,Lutris 科技公司
    2000 年 7 月

    內容:
     分析各種選擇
     約束數據
     利用約束
     來自 XML Java
     總結
     參考資料
     作者簡介

    在這個由四部分組成的系列文章的第一部分,我們將弄清什么是數據綁定,與在 Java 應用程序中處理 XML 數據的其它方法相比它有什么優勢,以及如何開始使用它。這一部分將考查為什么使用數據綁定,以及如何為各種約束建立模型,使 XML 文檔能轉換成 Java 對象。同時還涵蓋用于生成數據綁定類的輸入和輸出。

    您希望在您的 Java 應用程序中使用 XML 嗎?那么好,同成千上萬的其他人一起上這條船吧。當您深入了解 XML 以后,也許您會發現 DOM 和 SAX API(請參閱參考資料)不過是唬人的東西。您可能認為肯定存在某種簡單方法可以取得 XML 文檔,并通過 Java 應用程序訪問它,對嗎?不必通過回調或復雜的樹狀結構,而是使用像 setOwner(Stringowner)int getNumOrders() 這樣的方法,對嗎?如果您曾經沿著這一思路考慮問題,那么數據綁定就是您要尋找的解決方案。

    分析各種選擇
    當今各種 XML 和 XML 主義正泛濫成災(XSL、RDF、命名空間、RSS、XML Schema、XSLT...),您可能認為現在會有很多方法去訪問 Java 應用程序中的 XML 數據。令人驚訝的是,如果您尋根究底,實際只存在三種訪問 XML 數據的方法。沒錯 -- 只有三種方法,其中的一種還是最近隨一種新的 Java API 才出現的。

    應該這樣來看待這一問題:選擇范圍小使您更易于選出適合于您的方法。

    回調
    回調是作為一種事件驅動模型工作的。當分析 XML 文檔時,某些事件 -- 如文檔的起始和某個元素中的字符數據的起始 -- 將觸發回調方法。通過使用執行邏輯所需的數據,您可以實現這些事件的 Java 代碼。要弄清這種方法不能全靠直覺;開發人員通常要花費一段時間來理解和掌握回調模型的使用。SAX,用于 XML 的一種簡單 API,是這種 XML 使用方法的事實上的標準。


    更常見、更流行的是這種 API,它們取得一個 XML 文檔,然后創建數據的樹狀結構。XML 文檔成為樹首,充當一種容器。它有若干子級,如根元素。根元素又有其附加的子級,依此類推,直到(在某種意義上)獲得 XML 數據的一幅圖為止。因為幾乎每個大學生在某個階段肯定都處理過樹狀結構,所以這就可用作表示 XML 數據的一種非常直觀的方法。

    用于 XML 文檔樹狀表示的最流行的 API 就是 W3C 的推薦標準,即文檔對象模型 (DOM)。一種更新的 API,JDOM (這不是首字母縮寫詞)最近也正一直在推廣并流行開來。(雖然這個方案是我和 Jason Hunter 建立的,但我還得說實話。)另外,DOM 和 JDOM 都是 Spinnaker 方案設計的基本要求,Spinnaker 是一種新的 XML 分析器,它作為 Apache XML 方案的一部分正在開發之中。

    雖然樹狀 API 看起來比事件驅動的 SAX 更易于使用,但它們并不總是合適的。非常大的文檔可能需要大量的內存(尤其是使用 DOM 時);當對樹結構執行轉換 (XSLT) 時,系統可能停止運轉甚至徹底崩潰。雖然更新的 API(如 JDOM)能處理這些問題,但如果您必須處理極大量的數據,它們仍將是一個問題。并且,有時開發人員寧愿將 XML 文檔中的數據建模為一個簡單的帶有值的讀寫方法的 Java 對象,而不用樹狀模型工作。例如,開發人員會寧愿不去訪問名為 skuNumber 的子節點并設置該節點的文本值,而只想調用 setSkuNumber("mySKU") 并繼續進行。

    數據綁定
    用 Java 代碼訪問 XML 數據的最新方法要依賴于一套新的 Java 方法和相關的 API,這些 API 仍在開發之中。數據綁定是由 Sun 構建的一種“Java 規范要求”(JSR-031,見
    參考資料),它設計用于使 Java 對象綁定到 XML 文檔更加方便,這樣就使一種格式能夠容易地轉換為另一種格式,反之亦然。綁定引用一個具有讀寫方法的 Java 對象,讀寫方法都會影響到底層的 XML 文檔,并且也都直接映射為 XML 文檔中的元素及特征的名稱。當您進入到本系列文章下一部分中的某些細節時,這一說明會更有意義,但在目前,只說一點就夠了:這樣做使 XML 文檔特征 name 能夠通過一個稱為 setName() 的方法,來更改它的值,就像我上面暗示的那樣。

    這種訪問方式正在得到普及,并且當在 XML 文檔中存儲配置信息時特別有用。許多開發人員發現,它非常便于直接訪問所需的參數,而無須使用更復雜的樹狀結構。雖然這種訪問對于文檔轉換或消息傳送沒有什么用處,但它對于簡單數據處理是極其方便的。它是我們在本文及本系列文章中關注的第三種使用 XML 的方法。

    (當然,任何方法隨后都會引出一系列新的術語,所以請查看術語解釋以了解這些新的行話。)

    是否任何 XML 文檔都可以轉換為 Java 對象?還是僅有某些類型的 XML 文檔才可以?問得好!您很可能只希望將滿足一組約束條件的文檔轉換為 Java 對象。這與定義 Java 接口的方法類似:您確保只實例化和使用適應該接口的對象,允許就如何操作該對象作出假定。同樣,您只允許將滿足一組約束條件的 XML 對象轉換成 Java 對象;這使您能夠按希望的方式來使用所創建的對象。

    約束數據
    在研究代碼之前,您需要回答幾個有關如何表示 XML 數據的問題。這是數據綁定的最具挑戰性的方面之一。是為每個文檔創建一個新類,還是創建某個現有類的一個實例?您要使用哪個現有類?并且最重要的是,您正在處理的文檔是否適宜轉換為 Java 對象?

    那是一大堆問題,但您將在這里找到全部答案。將這些問題看作一系列決策點,一系列選擇。首先,您必須確定您能否從該 XML 文檔創建 Java 對象(如前面所討論的那樣)。如果能,您就要決定轉換應該以新 Java 類的形式出現,還是僅以現有類的一個實例的形式出現。最后,如果選擇了現有類,那么使用哪個類呢?結果就是各種各樣的決策樹。

    如果我們考察清單 1 中所示的一個示例 XML 文檔,然后再來處理這些問題,則決策樹的意義就更加清楚了。此示例文檔表示 Enhydra Application Server 中某個服務(具體說就是一個 web 容器)的配置。

    清單 1. 一個用于配置 Enhydra 中的 web 容器的 XML 文檔
    <?xml version="1.0"?>
    
    <webServiceConfiguration 
        version="1.0"
        name="My Web Container"
    >
    
      <port number="80"
            protocol="http"
            protected="false"
      />
    
      <document root="/usr/local/enhydra/html"
                index="*.html,*.xml"
                error="error.html"
      /> 
    
    </webServiceConfiguration>       

    此配置文檔包含有關服務本身的版本和名稱的信息,以及幾個嵌套的項目,每個項目都表示有關該 web 容器服務的一些附加信息。它給出了有關端口的詳細信息(包括端口號、協議和安全性),也給出了文檔服務信息(包括文檔根、用于索引頁的默認擴展名以及錯誤頁)。所有這些合在一起,就是配置一個新的 web 容器服務所需的全部信息。

    記住這個示例,您就可以開始回答數據表示的各個問題了。

    是否適合轉換?
    絕對適合!只要看一看
    清單 1 中的 XML 文檔就會發現,它表示一個對象(總體配置對象),具有若干特征或變量。其中某些變量又是另外的對象(端口和文檔),這些對象又具有它們自己的特征。實際上,這是適合轉換為 Java 對象的 XML 文檔的一個極好例子。為了進一步保證此對象是可用的,稍后我將向您展示一種方法來約束文檔中的數據。但是,還是先讓我們繼續沿著決策樹往下走。

    轉換成類還是實例?
    解決適宜性問題以后,現在就可以作出決定,是將每個 XML 配置文檔都變為一個全新的 Java 類呢,還是簡單地將其變為某個現有類的一個新實例。換句話說,就是到底應該生成新代碼,還是利用現有的代碼。照這樣來看,這就變成了一個簡單的可重用性問題。更容易且更明智的做法是,為每個 XML 文檔生成現有類的新實例。如果您一定要嘗試一下從每個文檔創建一個新的 Java 類,則得到的各個類之間可能沒有兼容性 -- 即兩個完全相同的文檔可能導致兩個不同的 Java 類!

    不用這個可能引起混亂的方法,您可以采用一組 XML 約束條件(由一個 DTD 或 XML 方案表示,將在下面講述),并根據這些約束條件來生成一個 Java 類(或多個類,根據需要)。這個生成的類將表示符合這些約束條件的任何 XML 文檔;這些 XML 文檔中的每一個都將被解包到生成的類的一個實例中。在這種情況下,就可以為表示 web 服務配置的文檔定義約束條件。這些約束條件將被映射為一個 Java 類,我們將稱之為 WebServiceConfiguration。然后您就可以獲得任何一種表示特定 web 服務配置的 XML 文檔,并假定此文檔符合我們的約束條件,由它而創建出前面生成的類的一個實例。這將允許應用程序將不同的 XML 文檔用作相同類型的對象,只要這些文檔中的數據對于該對象設計時要達到目的來說是有效的即可。

    新類還是現有的類?
    現在您也已經有條件回答下一個問題了:您希望創建一個現有類即 WebServiceConfiguration 類的一個實例。剩下需要弄清的全部事情是,這個類是如何預先生成的。所以,現在請將您的注意力集中在這樣一個問題上:如何獲得一組約束條件,用 XML 實現它們,并保證文檔符合這些約束?再一個問題就是,您如何再從這些約束條件生成一個可重用的 Java 類?

    利用文檔約束條件
    既然您知道此文檔將轉換成一個 Java 實例,這就產生了另一個問題:要考慮到必須以某種方式保證可將此文檔正確地解包到一個選定的 Java 類中。缺少變量或數據類型不正確都可能導致在解包過程中出錯 -- 或者甚至在客戶機訪問配置錯誤的容器時出現運行時異常。

    最好的情況是,在實際的解包過程開始之前,文檔的作者能夠保證,配置文檔對于他們選擇用來表示數據的類是“合法的”。閱讀到這一方案的 XML 人士說不定就會轉動他們的眼睛并嘀咕說,“好吧,當然您將使用 XML 文檔約束條件?!贝_認數據對選定類的合法性可以通過引用 DTD (文檔類型定義)或 XML 方案來完成。

    通過使用一組用外部 DTD 或方案文件表示的約束條件,文檔作者就可以在這些數據的“接口”上測試配置數據。換句話說,您可以這樣來建立應用程序,使之能夠對照所需的數據來檢查包含在 XML 實例文檔中的數據,而所需數據則是在文檔約束條件的外部文件中指定的。這樣,您就可以為數據創建一個接口。

    在使用 DTD 方案還是使用 XML 方案之間作出決策是一種相當簡單的選擇:因為 Java 語言是高度類型化的,所以我們希望能在 XML 文檔中支持類型化。例如,數據接口應該能夠驗證,為 web 容器的端口號提供的是整數,而不是字符串,后者在服務啟動時將引起錯誤。DTD 不支持類型檢查,所以我們無疑應該選擇 XML 方案。雖然 XML 方案在規范的領域在有一點不確定性,但它在很大程度上已趨于穩定,并可望在年內定型。我們可以在一個 XML 方案中編寫數據約束條件,然后用這個方案驗證可能的實例文檔,以確保解包能在這些實例文檔上進行。下面的 XML 方案表示我們的 web 容器服務的數據接口。

    清單 2. 表示一個 web 容器配置文檔的數據接口的 XML 方案
    <?xml version="1.0"?>
    
    <schema targetNamespace="http://www.enhydra.org"
            xmlns="http://www.w3.org/1999/xmlSchema"
            xmlns:enhydra="http://www.enhydra.org"
    >
    
      <complexType name="ServiceConfiguration">
        <attribute name="name" type="string" />
        <attribute name="version" type="float" />
      </complexType>
    
    
      <element name="serviceConfiguration" type="ServiceConfiguration" />
    
      <complexType name="WebServiceConfiguration" 
                   baseType="ServiceConfiguration"
                   derivedBy="extension">
        <element name="port">
          <complexType>
            <attribute name="protocol" type="string" />
            <attribute name="number" type="integer" />
            <attribute name="protected" type="string" />
          </complexType>
        </element>
    
        <element name="document">
          <complexType>
            <attribute name="root" type="string" />
            <attribute name="index" type="string" />
            <attribute name="error" type="string" />
          </complexType>
        </element>
      </complexType>
    
      <element name="webServiceConfiguration" type="WebServiceConfiguration" />
    
    </schema>

    清單 2 中的 XML 方案定義了幾個不同的數據對象,它們合起來表示一個 web 服務的配置對象。首先,定義了一個核心服務配置(serviceConfiguration),它包含版本和名稱。這可用作所有服務(如負載均衡服務、EJB 容器,當然還有我們的 web 服務)的基本對象。然后,作為此基本服務的擴展,又定義了 web 服務配置(webServiceConfiguration)。請注意,Java 成型之后,方案就已經為數據接口建立了模型。我們將附加的 web 服務屬性 portdocument 添加到 versionname 基本屬性中。這些屬性本身都是對象,具有它們自己的屬性(protocol、rooterror 等)。

    在此方案的定義方式中,特征代表簡單的 Java 類型,通常是原始 (primitive) 類型。這樣,nameversion 就分別成為類型 Stringfloat 的 Java 原始類型。portdocument 這樣的元素成為 Java 對象,它們可以有自己的屬性,還是用特征來表示。這樣就出現了遞歸現象:元素變成新對象,并對它的每個屬性進行檢查。如果屬性是一個特征,就為此對象創建一個簡單的 Java 原始成員變量;如果屬性是元素,則創建一個新的對象,并作為一個成員變量將其添加,然后在這個新對象上又開始同樣的過程,直到全部類都已創建為止。

    從蘿卜 ... 嗯 ... XML 獲得 Java
    一旦創建了 XML 方案,您就需要從這個方案中提取出必需的信息,來確定應該創建哪些 Java 類。這個過程的第一步是查看 XML 方案,并嚴格確定輸出應該是什么。對于簡單的 serviceConfiguration 對象,定義了兩個 Java 原始屬性:nameversion。對于這樣一個簡單的對象,確定所需的接口并不難。只需將被定義類型的名稱的首字母大寫,并將這些 Java 屬性添加到接口中即可,如清單 3 所示。

    清單 3. 為 ServiceConfiguration 接口而從 XML 方案生成的 Java 代碼
    public interface ServiceConfiguration {
        public void setVersion(float version);
        public float getVersion();
        public void setName(String name);
        public String getName();
    }

    這是相當明白易懂的;清單 3 中的接口為 XML 方案中定義的屬性提供讀方法和寫方法。另外,您將需要生成一個實現類來定義此接口的各個成員變量,并實現此接口中的每個方法。這種使接口從實現中分離出來的方法使我們能夠為特定的需要提中供多種實現。 例如,某個特定的服務可能需要執行計算,而不只是接受從寫方法中收到的值。現在考慮那種更復雜的情況還有點為時尚早,但我將在后續文章中重新提到它。然而,一般說來,您仍可以確定實現類應該像什么樣子,如清單 4 所示。

    清單 4. 為 ServiceConfiguration 實現而從 XML 方案生成的 Java 代碼
    public class ServiceConfigurationImpl implements ServiceConfiguration {
        private String name;
        private float version;
    
        public void setVersion(float version) {
            this.version = version;
        }
    
        public float getVersion() {
            return version;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getName() {
            return name;
        }
    }

    相同的原則也適用于 XML 方案中定義的其它對象。您可以在下面查看到其它 Java 類(因為它們都是應該生成的):

    總結
    到目前為止,您應該對數據綁定的各個方面都比較熟悉了。我已初步介紹了您應該使用數據綁定的原因,尤其是在配置信息的范圍內,并概述了為實現此方法您所需要了解的一些基本概念。

    此系列文章的下一篇將繼續考察數據綁定的過程。您將有機會去檢查 org.enhydra.xml.binding.SchemaMapper 類,它將接受這第一部分中創建的 XML 方案作為數據接口,并從它創建出一個 Java 接口和實現類。本系列文章的第二部分將詳細說明這一過程的每個步驟,并說明如何確保方案被準確表示,以便 XML 文檔能接著被轉換為生成的類的實例。

    梳理一下您學到的 XML 方案和 JDOM (我將在示例代碼中使用它們),下個月再見!

    參考資料

    • 下載包含本文中的示例代碼的 zip 文件,包括所有 Java 類XML 文件
    • 從 David Megginson 的 SAX 頁下載 The Simple API for XML (SAX) 的 2000 年 5 月版,這是一個基于事件的 API,用于在 Java 應用程序中讀取 XML。
    • 從 W3C DOM 工作小組的正式網頁上不斷了解 DOM 的最新狀態,DOM 即文檔對象模型 (DOM),該模型是一種基于樹的 API,用于在 Java 應用程序中讀寫 XML。
    • 下載 JDOM,這是一種使 XML 在 Java 應用程序中的使用更加簡單和直觀的 API,并了解有關 JDOM 方案的內容。
    • 研讀 JSR-031:數據綁定,這是 Sun 的數據綁定規范要求。
    • 下載 Enhydra,一種開放源代碼的 Java 應用程序服務器。
    • 從 W3C 的網站閱讀由兩部分組成的 XML 方案規范(目前為工作初稿)的最新細節:結構數據類型
    • Brett McLaughlin 有能力寫一本關于 Java 應用程序和 XML 這一主題的書 -- 他也這樣做了:訂購《Java and XML》,由 O'Reilly 出版。
    • 需要關于 XML 更基本的導論嗎?試一試 developerWorks 的 XML 導論教程和其它教學性內容,其中包括了大多數基本主題。

    作者簡介
    Brett McLaughlin 是 Lutris 科技公司的 Enhydra 戰略家,其專長是分布式系統的體系結構。他是《
    Java and XML》(O'Reilly) 一書的作者。Brett 涉足多種技術,如 Java servlets、Enterprise JavaBeans 技術、XML 和企業對企業的應用程序等。最近他與 Jason Hunter 一起建立了 JDOM 方案,該方案提供簡單的 API 來在 Java 應用程序中操作 XML。他還是 Apache Cocoon 項目和 EJBoss EJB 服務器的積極開發人員,并且是 Apache Turbine 項目的共同創始人之一??梢酝ㄟ^ brett@newInstance.com 與 Brett 聯系。

    posted on 2005-03-24 06:10 閱讀(221) 評論(0)  編輯  收藏 所屬分類: Java_Xml

    主站蜘蛛池模板: 亚洲а∨天堂久久精品9966| 一级午夜免费视频| 全部免费毛片在线| 两个人的视频www免费| 亚洲大香人伊一本线| 免费人成视频在线观看不卡| 久久青草精品38国产免费| 精品国产成人亚洲午夜福利| 一本色道久久综合亚洲精品| 精品久久8x国产免费观看| 免费福利在线观看| 亚洲最大的视频网站| 亚洲日韩国产成网在线观看| 免费大片黄在线观看yw| 国产高清对白在线观看免费91| 中文字幕版免费电影网站| 亚洲youjizz| 亚洲成a人片在线观看无码| 一二三四在线观看免费高清中文在线观看 | 亚洲精品国产福利一二区| 99爱视频99爱在线观看免费| 日本亚洲欧美色视频在线播放 | 国产精品亚洲片在线观看不卡| 国产尤物在线视精品在亚洲| 亚洲91av视频| 亚洲第一成人影院| 久久久久久精品免费看SSS| 中文在线日本免费永久18近| 亚洲妇女无套内射精| 亚洲色图综合网站| 亚洲国产精品无码久久SM| 免费萌白酱国产一区二区| 波多野结衣在线免费视频| 99久久久国产精品免费牛牛 | 国产成人无码精品久久久免费| 久久久久久亚洲精品不卡| 日韩在线免费视频| 亚洲免费视频在线观看| 最新久久免费视频| 一级毛片视频免费| 日韩a毛片免费观看|