日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

實(shí)用數(shù)據(jù)綁定: JaxMe——這一領(lǐng)域的新手

 shaobin0604@163.com 2007-01-23

2004 年 7 月 01 日

本 專欄的上一期全面概括了 JAXB,為您學(xué)習(xí)不同的數(shù)據(jù)綁定實(shí)現(xiàn)作好了準(zhǔn)備。本文開始深入考察 JaxMe,它是 JAXB 的一種開放源代碼實(shí)現(xiàn)。除了對基本 JAXB 規(guī)范作了一些改進(jìn)之外,JaxMe 還集成了數(shù)據(jù)庫和 Enterprise JavaBeans,這是對基本數(shù)據(jù)綁定行為的重要擴(kuò)展。您可以通過 “XML 和 Java 技術(shù)”討論論壇與作者和其他讀者交流您對本文的看法。(您也可以單擊本文頂端和底端的 討論來訪問論壇。)

SUN 的 JAXB,即 Java API for XML,曾經(jīng)受到廣泛的批評,這并不是一個秘密。在早期的版本(beta 或者其他某個版本)中,它是基于 DTD 的,完全不支持 W3C XML Schema。這種狀態(tài)持續(xù)了一年多,然后,JAXB 突然發(fā)布了 1.0 版。雖然這個版本解決了模式的支持問題,卻完全拋棄了 DTD,開發(fā)人員編寫的代碼(當(dāng)然是對 beta 軟件)突然不能使用了。近來,JAXB 得到了一些支持,但它仍然是一個非常封閉的環(huán)境,并在實(shí)現(xiàn)中留下許多很深的隱患。

本文將介紹的 JaxMe 項(xiàng)目保留了 JAXB 的許多好的特性,并克服了它的很多不足。首先 JaxMe 是源代碼開放的(在 Apache 的大傘之下),這意味著即使它現(xiàn)在就消失了,開發(fā)人員也仍然能夠使用甚至修改它的源代碼,從而保證依賴于它的那些代碼仍然能夠很好地運(yùn)行。如果說這一點(diǎn)還 不夠,JaxMe 還提供了數(shù)據(jù)庫交互、對 Enterprise JavaBeans 的支持等很多好的特性。

為了幫助您使用 JaxMe,我將詳細(xì)地介紹類生成的方法。雖然這只是一項(xiàng)非常基本的任務(wù),但可以幫助您熟悉 JaxMe,從而可以了解那些更有趣的特性。。

基本設(shè)置

設(shè)置 JaxMe 非常輕松。請?jiān)L問 JaxMe 項(xiàng)目站點(diǎn)(請參閱 參考資料鏈接),并從 Apache 鏡像站點(diǎn)下載其二進(jìn)制形式。在撰寫本文的時候,我下載的文件是 incubated-jaxme-0.2-bin.tar.gz。(在發(fā)布本文之前剛剛出現(xiàn)了 0.3 版,方法一樣,只不過文件名改成了 incubated-jaxme-0.3-bin.tar.gz)。在您的開發(fā)機(jī)器上對該文件進(jìn)行解壓縮。雖然可以在命令行中使用 JaxME,但是這樣做太痛苦了(因?yàn)橛? 太多的JAR 文件),本文使用 Ant 來處理 JaxMe 任務(wù)。強(qiáng)烈建議您也這樣做,這里包括所有相關(guān)的 Ant 文件,而且很容易根據(jù)需要進(jìn)行修改。





回頁首


類生成

和 Jaxb 一樣,在用 JaxMe 做某些工作之前需要一些 XML。清單 1 是一個非常簡單的 XML 模式,它定義了一個學(xué)生。當(dāng)然這里的定義很不完善,但是為了把精力集中到 JaxMe 而不是模式的語義上,有必要保持示例的簡單性。



清單 1. 簡單的學(xué)生模式
<?xml version="1.0" encoding="UTF-8"?>
                    <schema
                    xmlns="http://www./2001/XMLSchema"
                    xml:lang="EN"
                    targetNamespace="http://dw.ibm.com/jaxme/student"
                    xmlns:stu="http://dw.ibm.com/jaxme/student"
                    elementFormDefault="qualified"
                    attributeFormDefault="unqualified"
                    >
                    <element name="Student">
                    <complexType>
                    <sequence>
                    <element name="firstName" type="string" />
                    <element name="lastName" type="string" />
                    <element name="address" type="stu:Address" />
                    </sequence>
                    </complexType>
                    </element>
                    <complexType name="Address">
                    <sequence>
                    <element name="name" type="string"/>
                    <element name="street" type="string"/>
                    <element name="city" type="string"/>
                    <element name="state" type="string"/>
                    <element name="zip" type="positiveInteger"/>
                    </sequence>
                    </complexType>
                    <complexType name="College">
                    <sequence>
                    <element name="name" type="string" />
                    <element name="address" type="stu:Address" />
                    </sequence>
                    </complexType>
                    </schema>
                    

如果已經(jīng)正確地設(shè)置了 Ant 構(gòu)建過程(本文的 最后還會詳細(xì)加以說明),只需輸入 ant generate 就可以從這個模式生成類。我將這些細(xì)節(jié)留在了文章的最后,以便在閱讀本文的過程中您能夠把精力放在 JaxMe 及其語義上,最后再專門看一看 Ant。實(shí)際上,我建議您先通讀一遍本文,然后再逐段地測試代碼。這樣,在您實(shí)際輸入代碼的時候,就已經(jīng)掌握了其中的概念,可以更快地解決其中遇到的問 題。

包規(guī)范

所有生成的類都將放在 targetNamespace 屬性指定的包中。這種約定是 JaxMe 獨(dú)有的,因此,您應(yīng)該好好地理解它的工作原理??匆豢醋鳛樵搶傩詤?shù)提供的 URI: http://dw.ibm.com/jaxme/student 。這個字符串將被 JaxMe 模式編譯器轉(zhuǎn)化成包的名稱。首先去掉“http://”,然后 逆轉(zhuǎn)URI 中的主機(jī)名部分(這里就是“dw.ibm.com”),得到“com.ibm.dw”。這看起來有點(diǎn)奇怪,但實(shí)際上是通常的打包機(jī)制,對于用于開發(fā)特定站點(diǎn)或者 Bean(特別是標(biāo)簽庫的包),這非常合理。

最后,URI 的剩余部分用斜杠( / )分隔,并將它們附加到從主機(jī)名派生的包名的后面。因此對于清單 1 中的模式,完整的包就是 com.ibm.dw.jaxme.student 。這個模式生成的所有類都將放在這個包中。

XML 語義

除了為 JaxMe 提供信息之外, targetNamespace 屬性對于 XML 還有一些特殊的意義。它告訴模式處理程序?qū)⑺袆?chuàng)建的構(gòu)造(如 Address 這樣的復(fù)雜類型)都放在該名稱空間中。這意味著您需要通過這個名稱空間引用這些構(gòu)造,如果名稱空間很長,則應(yīng)該定義一個前綴映射到該名稱空間。

注意:如果不能理解上面那一句話,您可能需要在學(xué)習(xí)一下 XML,特別是如何將 XML Schema 用于 XML。有關(guān)的更多信息,請參閱文章后面的 參考資料(以及 developerWorks XML 專區(qū)的其他文章)?,F(xiàn)在不妨繼續(xù)讀下去,請相信我,但是要成為一名 JaxMe 專家,就必須花一些時間完全理解名稱空間。

清單 1 的模式中,引用是通過 stu 前綴實(shí)現(xiàn)的。通過這個前綴,您可以很容易定義類型,然后通過模式引用它們(使用名稱空間前綴)。

還應(yīng)該知道,JaxMe 大量使用 include 指令(該例中未使用)。特別是對于大型模式,您可以將這些定義分段放在不同的文件中,然后在最高層的模式中使用下面方式引用它們:

<!-- Include definitions from another XML Schema -->
                    <include schemaLocation="file:///dev/jaxme/supplemental/datatypes.xsd"/>
                    

XML 模式處理程序?qū)⑿畔⑥D(zhuǎn)移給 JaxMe,而對這些文件完全不作區(qū)分,因此我們建議,如果需要就使用多個模式。





回頁首


得到的類

生成類之后,花點(diǎn)時間熟悉一下生成的結(jié)果。雖然這些類與 JAXB 創(chuàng)建的構(gòu)造非常類似,但也存在少量細(xì)微的差別。

Student.java

它表示一個 XML 元素(來自 清單 1),是類層次的基本結(jié)構(gòu)。實(shí)際上,它只是一個簡單的接口,擴(kuò)展了 StudentType (由 JaxMe 生成)和 Element ,后者是 JaxMe 運(yùn)行時 API 的一部分。當(dāng)然,這個類(以及所有其他生成的類)都在 com.ibm.dw.jaxme.student 包中。

StudentType.java

JaxMe 中任何名為 XXXType (其中 XXX 是像“Student”或“Address”這樣的名稱)的對象都是從模式中派生的定義。清單 2 顯示了這個類的源代碼,其中的內(nèi)容非常簡單。



清單 2. 生成的 StudentType 代碼
package com.ibm.dw.jaxme.student;
                    public interface StudentType {
                    public String getFirstName();
                    public void setFirstName(String pFirstName);
                    public String getLastName();
                    public void setLastName(String pLastName);
                    public AddressType getAddress();
                    public void setAddress(AddressType pAddress);
                    }
                    

所有的屬性都有訪問( getXXX() )和修改( setXXX() )方法。當(dāng)然,無論是簡單字符串類型和更加復(fù)雜的類型,如 Address ,這些類型都用類表示,后面帶有“Type”,因此在生成的清單中會看到對 AddressType 的引用。

AddressType.java 和 CollegeType.java

現(xiàn)在您已經(jīng)看到了 清單 2StudentType.java,這些代碼非常簡單,您可以自行加以分析。

ObjectFactory.java

該文件在很多方面是 JaxMe 和特定于域的類之間的橋梁,最重要的方法有:

  • newInstance() 在特定于域的上下文中創(chuàng)建一個新元素并返回它。
  • createStudentType() 新創(chuàng)建的頂級 Student 元素。

非常奇怪的是,任何 JaxMe 文檔中都沒有提到該文件,提供的示例中也沒有使用它。我個人倒是發(fā)現(xiàn)了它的某些用處,但是不建議您依賴該文件。不需要它也能完成所有的工作,如果有意在文檔中忽略它,那么很可能在將來的版本中該文件就不會再出現(xiàn)。

Configuration.xml

該 XML 文件處理從 XML 到 Java 代碼(或者相反)的映射。它將元素和類、字段和屬性等聯(lián)系起來。清單 3 給出了該例中相當(dāng)簡單的映射文件。



清單 3. 樣例代碼的 Configuration.xml
<Configuration xmlns="http://ws./jaxme/namespaces/jaxme2/configuration">
                    <Manager validatorClass="com.ibm.dw.jaxme.student.impl.StudentTypeValidator"
                    qName="{http://dw.ibm.com/jaxme/student}Student"
                    marshallerClass="com.ibm.dw.jaxme.student.impl.StudentTypeSerializer"
                    handlerClass="com.ibm.dw.jaxme.student.impl.StudentHandler"
                    elementInterface="com.ibm.dw.jaxme.student.Student"
                    elementClass="com.ibm.dw.jaxme.student.impl.StudentImpl"/>
                    <Manager validatorClass="com.ibm.dw.jaxme.student.impl.AddressTypeValidator"
                    marshallerClass="com.ibm.dw.jaxme.student.impl.AddressTypeSerializer"
                    handlerClass="com.ibm.dw.jaxme.student.impl.AddressTypeHandler"
                    elementInterface="com.ibm.dw.jaxme.student.AddressType"
                    elementClass="com.ibm.dw.jaxme.student.impl.AddressTypeImpl"/>
                    <Manager validatorClass="com.ibm.dw.jaxme.student.impl.CollegeTypeValidator"
                    marshallerClass="com.ibm.dw.jaxme.student.impl.CollegeTypeSerializer"
                    handlerClass="com.ibm.dw.jaxme.student.impl.CollegeTypeHandler"
                    elementInterface="com.ibm.dw.jaxme.student.CollegeType"
                    elementClass="com.ibm.dw.jaxme.student.impl.CollegeTypeImpl"/>
                    </Configuration>
                    

目前,JaxMe 要求直接修改該文件來改變映射。最常見的變化是您可能希望用自己的類代替生成的類。當(dāng)然,您必須(至少對 JaxMe 的當(dāng)前版本而言)生成默認(rèn)的類, 然后再修改該文件。同樣值得注意的是,實(shí)際上這種行為沒有得到支持,盡管映射支持這樣做,但是沒有經(jīng)過很好的測試,也沒有很好的文檔說明。

提示:將來的文章中我可能還要詳細(xì)地討論這種行為。如果對此感興趣,請給我發(fā)電子郵件或者上傳對本文的反饋意見,讓我知道!這是了解對特定主題的興趣要求的最好辦法。

jaxb.properties

這是標(biāo)準(zhǔn)的 JAXB 性質(zhì)文件,當(dāng)然也經(jīng)過了 JaxMe 的修改。其中只有一行,告訴 JAXB 工廠類使用 JaxMe 的實(shí)現(xiàn)類,如下所示:

javax.xml.bind.context.factory=org.apache.ws.jaxme.impl.JAXBContextImpl
                    

對熟悉 JAXP 的讀者而言,在實(shí)現(xiàn)方式上,這與 Xerces 要求 JAXP 體系結(jié)構(gòu)完成其實(shí)現(xiàn)是完全相同的。

impl/*.java

impl 子目錄中的各個源文件都是由 JaxMe 創(chuàng)建的接口的具體實(shí)現(xiàn)。一般來說不用關(guān)心這些文件,它們處理文檔的 XML 加工過程,將文檔轉(zhuǎn)換成 Java 中的等價物。

如果您喜歡刨根問底,那么可以告訴您這些類都是 SAX 類,因?yàn)?JaxMe 使用 SAX 解析 XML。事實(shí)上,Type 類(間接地)實(shí)現(xiàn)了 SAX 的 org.xml.sax.ContentHandler 接口。在源代碼中您還會看到 startDocument()characters() 這樣的方法(都列在這里的話太長了)。

雖然您可能不想對這些類太費(fèi)心思,但是對其有個基本的了解還是不錯的。您將會在代碼中使用它們(很快就會看到),您會發(fā)現(xiàn)理解這些類對于查錯和調(diào)試很有幫助。

編譯

觀察這些類的最后一個步驟就是編譯它們。這似乎是顯而易見的事,但是您恐怕難以相信那些因缺乏編譯而造成的問題,或者類路徑問題(稍后還會提到)。因此在使用這些類之前一定要編譯它們。同樣,我發(fā)現(xiàn)使用 Ant 來完成這項(xiàng)工作最簡單,因此我使用 ant compile 來完成這項(xiàng)任務(wù)。

對于喜歡苦差事(或者只是愛好輸入 javac )的人,類路徑中一定要包括 jaxme-api.jarjaxme.jar。 jaxme-api.jar包含 JAXB API,而 jaxme.jar 則包含 JaxMe 實(shí)現(xiàn)類。在輸出的時候,應(yīng)該將所有的輸出都放在基目錄和編譯后的 impl 目錄中。最后,您可能希望復(fù)制所用的支持文件: Configuration.xmljaxb.properties。在運(yùn)行時導(dǎo)入這些文件,以便對它們進(jìn)行編組和解組。





回頁首


使用 Ant 自動處理

您 會發(fā)現(xiàn)沒有什么好的替代構(gòu)建工具。好的工具可以為您節(jié)約反復(fù)處理類路徑問題的大量時間,也不用您去記住特定的命令行選項(xiàng)。本文中遇到的幾個問題都可以使用 Ant 來自動處理。我想花一點(diǎn)讓您看一看我的 Ant 文件,這樣您也可以把 Ant 結(jié)合到您的構(gòu)建環(huán)境中。我以后的文章中也可以略過這些細(xì)節(jié)(藝多不壓身,是不是?)。

類生成

首先,您會希望使用 JaxMe 模式編譯器/類生成工具,用 org.apache.ws.jaxme.generator.Generator 接口表示。因此,您完全可以使用 Ant 的 java 目標(biāo)創(chuàng)建該接口的一個實(shí)例。但是,這樣做有點(diǎn)麻煩——需要在實(shí)現(xiàn)中進(jìn)行硬編碼,而且必須將構(gòu)建文件和實(shí)現(xiàn)的變化混在一起。您可以將實(shí)現(xiàn)類定義為屬性,但是 這樣仍然存在非常低層的編碼混合問題。對于使用 Ant 的人來說,所幸的是 JaxMe 包括用于在構(gòu)建文件中插入類生成的 Ant taskdef (任務(wù)定義),它可以處理所有這些細(xì)節(jié)問題。假設(shè)您有一個定制的任務(wù)定義,如清單 4 所示:



清單 4. JaxMe 的 Ant taskdef
<path id="classpath.schema-generator">
                    <pathelement location="${lib}/jaxme2.jar" />
                    <pathelement location="${lib}/jaxmejs.jar" />
                    <pathelement location="${lib}/jaxmexs.jar" />
                    <pathelement location="${lib}/jaxmeapi.jar" />
                    </path>
                    <taskdef name="xjc"
                    classname="org.apache.ws.jaxme.generator.XJCTask"
                    classpathref="classpath.schema-generator"
                    />
                    

只要將這個片段插入 Ant 構(gòu)建文件,生成類就變得非常簡單。您可以使用清單 5 中的 XML 完成這項(xiàng)工作。



清單 5. 生成類
  <target name="generate" depends="init">
                    <xjc schema="student.xsd"
                    target="${dir.generated}">
                    <produces includes="com/ibm/dw/jaxme/student/*.java" />
                    </xjc>
                    </target>
                    

編譯

生成類之后,現(xiàn)在需要編譯并復(fù)制支持文件。清單 6 負(fù)責(zé)這項(xiàng)任務(wù),它甚至還處理了類路徑問題。



清單 6. 編譯類
  <path id="classpath.schema-compiler">
                    <pathelement location="${lib.jaxme}/jaxmeapi.jar" />
                    <pathelement location="${lib.jaxme}/jaxme2.jar" />
                    </path>
                    <target name="compile" depends="generate">
                    <javac srcdir="${dir.generated}"
                    destdir="${dir.build}">
                    <classpath refid="classpath.schema-compiler" />
                    </javac>
                    <!-- Copy over support files -->
                    <copy todir="${dir.build}">
                    <fileset dir="${dir.generated}">
                    <include name="**/jaxb.properties" />
                    <include name="**/Configuration.xml" />
                    </fileset>
                    </copy>
                    </target>
                    

清理

顯然,如果能夠清除所做的工作,然后重新開始新的工作常常是有益的。雖然這并非 JaxMe 特有的,但也值得看一看。通常的辦法是通過一個稱為 clean 的目標(biāo)(target)進(jìn)行清理,如清單 7 所示。



清單 7. 清理
  <target name="clean">
                    <delete dir="${dir.generated}" />
                    <delete dir="${dir.build}" />
                    </target>
                    

清單 8 是一個更大的 Ant 文件,它將這些成分集中到了一起。實(shí)際上這也是我一直在用的文件,該文件對于這里描述的所有內(nèi)容都適用。



清單 8. JaxMe Ant taskdef
<?xml version="1.0" encoding="UTF-8"?>
                    <project basedir=".">
                    <property name="lib.jaxme" value="/Users/bmclaugh/dev/lib" />
                    <property name="dir.build" value="build" />
                    <property name="dir.generated" value="generated" />
                    <path id="classpath.schema-generator">
                    <pathelement location="${lib.jaxme}/jaxme2.jar" />
                    <pathelement location="${lib.jaxme}/jaxmejs.jar" />
                    <pathelement location="${lib.jaxme}/jaxmexs.jar" />
                    <pathelement location="${lib.jaxme}/jaxmeapi.jar" />
                    </path>
                    <path id="classpath.schema-compiler">
                    <pathelement location="${lib.jaxme}/jaxmeapi.jar" />
                    <pathelement location="${lib.jaxme}/jaxme2.jar" />
                    </path>
                    <taskdef name="xjc"
                    classname="org.apache.ws.jaxme.generator.XJCTask"
                    classpathref="classpath.schema-generator"
                    />
                    <target name="init">
                    <mkdir dir="${dir.generated}" />
                    <mkdir dir="${dir.build}" />
                    </target>
                    <target name="generate" depends="init">
                    <xjc schema="student.xsd"
                    target="${dir.generated}">
                    <produces includes="com/ibm/dw/jaxme/student/*.java" />
                    </xjc>
                    </target>
                    <target name="compile" depends="generate">
                    <javac srcdir="${dir.generated}"
                    destdir="${dir.build}">
                    <classpath refid="classpath.schema-compiler" />
                    </javac>
                    <!-- Copy over support files -->
                    <copy todir="${dir.build}">
                    <fileset dir="${dir.generated}">
                    <include name="**/jaxb.properties" />
                    <include name="**/Configuration.xml" />
                    </fileset>
                    </copy>
                    </target>
                    <target name="clean">
                    <delete dir="${dir.generated}" />
                    <delete dir="${dir.build}" />
                    </target>
                    </project>
                    

您需要改變 lib.jaxme 屬性的值,然后就可以了。該例中只需要輸入 ant generate 就可以從模式生成類。您應(yīng)該把這類工具(以及 Ant)放在手邊,因?yàn)樗沟镁幾g和處理微妙的類路徑變得非常簡單。





回頁首


結(jié)束語

只要充分理解了 JaxMe 處理類生成的方式,就可以很容易的實(shí)現(xiàn)與 XML 的相互轉(zhuǎn)化。我將在下一篇文章討論這個問題,然后再介紹 JaxMe 某些專有的特性,比如使用數(shù)據(jù)庫。在這之前先用映射和 Configuration.xml來打發(fā)時間吧,但愿您過得愉快(也需要發(fā)一兩次火)并真正掌握 JaxMe 的工作原理。在這期間,我將開始撰寫下一期的稿子,那時再見吧。






回頁首


下載

名字大小下載方法
x-pracdb4-code.zip 2KB  FTP|HTTP
關(guān)于下載方法的信息 Get Adobe? Reader?


參考資料



關(guān)于作者

 

Brett McLaughlin 從 Logo 時代(還記得那個小三角嗎)就開始從事計(jì)算機(jī)。他目前專門使用 Java 相關(guān)技術(shù)構(gòu)建應(yīng)用程序基礎(chǔ)設(shè)施。最近幾年,他為 Nextel Communications 和 Allegiance Telecom, Inc. 實(shí)現(xiàn)了這些基礎(chǔ)設(shè)施。Brett 是 Java Apache 項(xiàng)目 Turbine 的締造者之一,該項(xiàng)目使用 Java servlet 為 Web 應(yīng)用程序開發(fā)建立了可重用的組件體系結(jié)構(gòu)。他還參與了 EJBoss 項(xiàng)目(一種開放源代碼的 EJB 應(yīng)用程序服務(wù)器)和 Cocoon(一種開放源代碼的 XML Web 發(fā)布引擎)。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多