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

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

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

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

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

    Brett McLaughlin
    Enhydra 戰(zhàn)略家,Lutris 科技公司
    2000 年 7 月

    內(nèi)容:
     分析各種選擇
     約束數(shù)據(jù)
     利用約束
     來自 XML Java
     總結(jié)
     參考資料
     作者簡介

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

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

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

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

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


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

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

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

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

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

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

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

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

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

    如果我們考察清單 1 中所示的一個示例 XML 文檔,然后再來處理這些問題,則決策樹的意義就更加清楚了。此示例文檔表示 Enhydra Application Server 中某個服務(wù)(具體說就是一個 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>       

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

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

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

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

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

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

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

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

    通過使用一組用外部 DTD 或方案文件表示的約束條件,文檔作者就可以在這些數(shù)據(jù)的“接口”上測試配置數(shù)據(jù)。換句話說,您可以這樣來建立應(yīng)用程序,使之能夠?qū)φ账璧臄?shù)據(jù)來檢查包含在 XML 實例文檔中的數(shù)據(jù),而所需數(shù)據(jù)則是在文檔約束條件的外部文件中指定的。這樣,您就可以為數(shù)據(jù)創(chuàng)建一個接口。

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

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

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

    從蘿卜 ... 嗯 ... XML 獲得 Java
    一旦創(chuàng)建了 XML 方案,您就需要從這個方案中提取出必需的信息,來確定應(yīng)該創(chuàng)建哪些 Java 類。這個過程的第一步是查看 XML 方案,并嚴(yán)格確定輸出應(yīng)該是什么。對于簡單的 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();
    }

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

    清單 4. 為 ServiceConfiguration 實現(xiàn)而從 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 類(因為它們都是應(yīng)該生成的):

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

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

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

    參考資料

    作者簡介
    Brett McLaughlin 是 Lutris 科技公司的 Enhydra 戰(zhàn)略家,其專長是分布式系統(tǒng)的體系結(jié)構(gòu)。他是《
    Java and XML》(O'Reilly) 一書的作者。Brett 涉足多種技術(shù),如 Java servlets、Enterprise JavaBeans 技術(shù)、XML 和企業(yè)對企業(yè)的應(yīng)用程序等。最近他與 Jason Hunter 一起建立了 JDOM 方案,該方案提供簡單的 API 來在 Java 應(yīng)用程序中操作 XML。他還是 Apache Cocoon 項目和 EJBoss EJB 服務(wù)器的積極開發(fā)人員,并且是 Apache Turbine 項目的共同創(chuàng)始人之一。可以通過 brett@newInstance.com 與 Brett 聯(lián)系。

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

    主站蜘蛛池模板: 日韩成人免费视频| 亚洲综合无码一区二区| 亚洲大片免费观看| 一级毛片免费不卡直观看| 性xxxx黑人与亚洲| 亚洲综合无码一区二区| 在线日韩日本国产亚洲| 免费A级毛片无码A| 韩国日本好看电影免费看| 国产h肉在线视频免费观看| 免费视频精品一区二区三区 | 免费国产在线精品一区| 亚洲乱码中文字幕小综合| 亚洲AV无码日韩AV无码导航| 在线精品亚洲一区二区三区| 亚洲精品无码成人片在线观看 | 亚洲乱码中文论理电影| 亚洲黄色免费电影| 久久伊人久久亚洲综合| 久久久久久久尹人综合网亚洲 | 国产黄色免费观看| 美女免费精品高清毛片在线视| 国产亚洲精aa在线看| 亚洲人成网站看在线播放| 亚洲人成电影网站| 亚洲中文字幕在线无码一区二区| 911精品国产亚洲日本美国韩国| 亚洲第一视频网站| 亚洲国产精品自在在线观看 | 国产午夜免费高清久久影院| eeuss草民免费| 国产免费久久久久久无码| a级毛片免费观看在线| 九九热久久免费视频| 97超高清在线观看免费视频| a级毛片毛片免费观看久潮 | 亚洲欧洲尹人香蕉综合| 亚洲专区一路线二| 亚洲av永久无码天堂网| 天天综合亚洲色在线精品| 日本免费精品一区二区三区|