Zeus可以將JAVA對象與XML文件進行綁定,綁定使數據在J2EE中的應用更加方便。本文主要介紹Zeus的編譯與使用。對綁定過程中使用的DTD和XML文件也有說明。
1、ZEUS簡介
Enhydra是以生長于美國加利福尼亞海邊的小水獺命名的非營利組織的名字。從但與聞名的Apache不同,Enhydra致力于圍繞
application Server的電子商務解決方案的研究。
Zeus就是Enhydra開發的眾多的工具軟件中的一個,功能是對JavaObject和XML進行數據綁定。它可以將任意的XML文件轉化為對應的JavaObject文件,并且將數據方便的在這兩種形式之間轉換。Zeus最新版本是Zeus1.0 Beta 3.5,由于是完全的
源碼開放,可以到 http://zeus.enhydra.org/software/downloads/index.Html下載源代碼后自己編譯。
2、預備知識
2.1 用XML作為數據載體
XML(Extensible Markup Language)由W3C組織制定并得到世界上幾乎所有大公司的支持。XML是一種非常靈活的文本格式,與HTML相比,XML延續了其簡單、易懂的語法,但是卻有了更大的靈活性和擴展能力。例1是一段描述Customer信息的XML文件,作為描述數據的語言,XML的組織形式很自由且表述清楚。
<?xml version="1.0" encoding="GBK"?>
<Customer Customer_No= "00001">
< Name>李俊</ Name>
<Id_No>210106421016001</Id_No>
<Sex >男</Sex>
<Birth_Place>大連</Birth_Place>
<Birth_Date>1942-10-16</Birth_Date>
<Nationality>中國</Nationality>
<EdUCation>高中</Education>
<Address>大連市沙河口</Address>
<Contact_Info Id = "00001">
<Z
ip_Code>116001</Zip_Code>
<Tel_No>2645677</Tel_No>
</Contact_Info>
</Customer>
例1:描述Customer的XML文件
這段XML結構很清楚:描述的是一個"顧客"實體,這個實體有其屬性:姓名、身份證號、性別、出生地、生日、出生地、聯系方式(郵編、電話)等。
第一行表述此XML文件的版本是1.0,用的是"GBK"的編碼方式(假如要解析中文,GBK或GB2312是必須的)。、是的子標記。而在< Contact>中還可以繼續包含子標記:、。用戶自定義tag的XML語言給了用戶足夠的自由度表示數據,但是也為顯示和解析帶來了難度,為了解決這一問題,W3C在格式控制和標記定義上對XML加以限制。例如就是一對不合格的標記。
2.2 DTD定義數據
DTD(Document Type Definition)目的是定義XML文檔中的元素和各元素間的關系。DTD可以與應用它的XML共存在一個文件中,也可以單獨成為一個文件。例2是一個描述例1所述的xml文件的DTD文件。
<?xml version="1.0" encoding="GBK"?>
<!ELEMENT Customer
(Name?,Id_No?,Sex?,Birth_Place?,
Birth_Date?,Nationality?, Education?,
Contact_Info?>
<!ATTLIST Customer
Customer_No CDATA #REQUIRED
>
<!ELEMENT Name (#PCDATA)>
<!ELEMENT Id_No (#PCDATA)>
<!ELEMENT Sex (#PCDATA)>
<!ELEMENT Birth_Place (#PCDATA)>
<!ELEMENT Birth_Date (#PCDATA)>
<!ELEMENT Nationality (#PCDATA)>
<!ELEMENT Education (#PCDATA)>
<!ELEMENT Contact_Info
(Zip_Code?,Tel_No?)>
<!ATTLIST Contact_Info
id CDATA #REQUIRED
>
<!ELEMENT Zip_Code (#PCDATA)>
<!ELEMENT Tel_No (#PCDATA)>
例2:DTD文件
無規矩不成方圓,例2的DTD文件定義了例1的XML描述的Customer元素,通過DTD的定義,XML中的標記都被賦予了意義,并且很好的解釋了Customer與其它元素之間的關系。DTD文件的存在使XML中的數據有了規定的形式,二者由如此緊密地聯系輕易聯想到另外一種重要的數據組織方式--
數據庫的表中的字段和數據。
DTD-XML這種與表結構-數據類似的結構為這兩種技術的相互轉換提供了天然的方便條件,借助于DTD,可以方便的將表中的數據用XML表示。
3、編譯你的Zeus
下載下來的Zeus是一個zip文件,假如選擇的是源代碼下載,就必須首先編譯才能夠使用。本文介紹zeus的使用,首先從源代碼的編譯說起。
編譯的方法在下載的docs文件夾中有詳盡的描述,作為Java技術陣營的一份子,Zeus在將自己完全奉獻的同時也使用了其他的一些杰出的Java工具。比如編譯就使用了Apache的Ant??梢栽赯eus/lib下找到Ant.jar文件。
在編譯之前唯一要做的事就是設定好
操作系統的JAVA_HOME環境變量。例如在windows系統,假如jdk安裝在D:/jdk1.3.1,則運行set JAVA_HOME = D:/jdk1.3.1。
完成了預備工作就可以開始編譯zeus,Ant本身是易于使用的編譯工具,build.xml文件可以設定所有編譯的細節和文件的組裝。Zeus的編譯文件位于根目錄下的build.xml,這個XML文件包含了對Zeus編譯并組裝zeus.jar文件的一切細節而且有很高的可讀性。
確定在zeus的根目錄下,運行./bin/build.bat targets,Ant可以找到位于當前目錄下的build.xml文件,假如不輸入任何參數,ant會輸出提示要你輸入編譯targets:
compile:編譯zeus的所有源代碼,并將之放置于build/classes下;
bin:將原src/bin下的文件拷到build/bin下,原lib目錄下的jar文件拷到build/lib下并將組合好的zeus.jar置于此文件夾下;
doc:編譯javadoc,并將結果拷到bin/docs/apidoc/下。
sample和test分別用于編譯例程和測試代碼。假如不想一步一步編譯,可以將targers參數設為all,這樣ant就會以正確的次序為你自動編譯好所有的targets。編譯后的會出現一個build文件夾,所有編譯好的文件都在這個文件中。
檢查build/bin文件夾,出現的Zeus.jar文件就是編譯好的工具。假如你有足夠的經驗去修改Zeus的源代碼和build.xml文件,完全可以打造屬于你自己的Zeus。
4、生成描述XML的Java對象
生成Java對象的第一步是使用Zeus自動生成Java源代碼。使用zeus的批處理文件在build/bin/的zeus.bat,使用語法如下:
zeus.bat -constraints=
[-outputDir=]
[-collapseSimpleElements=]
[-ignoreIDAttributes=]
[-javaPackage=]
[-root=]
將例1的XML文件與Java Objects綁定,第一步要生成Java文件,具體方案就是使用Zeus.jar中的org.enhydra.zeus.util.DTDSourceGenerator,例2中的Customer.dtd文件作為必須的constrains參數。首先執行下列命令:
將Customer文件置于c:/zeus/dtd文件下,建立c:/zeus/zjhsample,執行下列命令:
C:/zeus>./build/bin/zeus.bat
-constraints=dtd/Customer.dtd
-outputDir=zjhsample -javaPackage
=com.zjh.zeustest.binding
-collapseSimpleElements=true
查看
c:/zeus/zjhsample/com/zjh/
zeustest/binding文件夾,
發現生成了六個文件:
Customer.java、CustomerImpl.java、
Contact_Info.java、Contact_InfoImpl.java、
CustomerUnmarshaller.java、
Unmarshallable.java。
生成的類名有規可循:Customer、Contact_info是DTD文件中非簡單元素的名稱,Zeus生成與其同名的接口;CustomerImpl、Contact_infoImpl是實現這兩個接口的類。CustomerUnmarshaller與Unmarshallable看起來有些希奇,但也不是憑空而來:Unmarshallable接口繼續自org.xml.sax.ContentHandler,提供解析XML合法性的接口,所有的ElementImpl類都要繼續該接口;CustomerUnmarshaller提供反解碼XML的接口,將XML文件輸入,返回Customer對象。
數據綁定的所有秘密都隱藏在這幾個文件中,可以用任何的文本編輯器對其進行編輯。但是就像程序聲明所述:修改這些程序也許會導致數據綁定操作的失敗。
最后編譯這六個java文件:javac *.java,生成class文件。這樣,就得到了用于描述XML文件的Java類。
5、Marshal與Unmarshal--XML與JAVA Object的轉換
通用的XML文件適合不同技術平臺之間的數據傳輸,Java對象可以為Java程序提供更加方便的使用接口,通過Zeus工具生成的Java Object就像是一座橋梁,將二者緊密地聯系在一起(見圖1)。它不僅在內部構建了足夠的用來描述XML文件各個元素值的屬性,更提供了可以將Java對象與XML文件相互轉化的接口:Unmarshal和Marshal。
Unmarshal:將XML文件"反解碼"為JavaObject;
Marshal:將JavaObject"解碼"為XML文件。

圖1:Java對象與XML文件的轉換
5.1 Unmarshal XML文件到Java對象
一旦用Zeus生成的Java對象被編譯,將XML文件轉化為Java形式的表述就變成了一件簡單且舒服的事。這一過程被描述為"反解碼(Unmarshal)",其實它是Zeus根據DTD文件生成的ElementImp對象的Unmarshal()方法。
如同科幻小說中的物品自動制造機,向Unmarshal方法投入以Java File、Writer、或InputStream形式包裝的XML文件,一按Unmarshal按鈕,XML數據的Java表示版就輕而易舉的誕生了。示例程序(例3)中的CustomerUnmarshal類完成了Unmarshal例1中customerInfo.xml的工作,并把結果輸出到屏幕上。
package com.zjh.zeustest;
import java.io.*;
import com.zjh.zeustest.binding.*;
public class CustomerInfo
{
public static void
main(String[] args)
{
if(args.length!=1)
{
System.out.
PRintln
("please in put the location of XML file");
return;
}
try{
Customer customer =
CustomerUnmarshaller.unmarshal
((new File(args[0])),false);
System.out.println
("姓名:"+customer.getName());
System.out.println
("證件號碼:"+customer.getId_No());
System.out.println
("性別:"+customer.getSex());
System.out.println
("出生地:"+customer.getBirth_Place());
System.out.println
("國籍:"+customer.getNationality());
System.out.println
("學歷:"+customer.getEducation());
System.out.println
("郵政編碼:"+customer.getContact_Info()
.getZip_Code());
System.out.println
("電話號碼:"+customer.
getContact_Info().getTel_No());
}catch(Exception e){
e.printStackTrace();
}
}
}
例3 Unmarshal XML
編譯該程序后用下列命令運行:
java -classpath ./;../lib/xerces.jar
com.zjh.zeustest.Customer Unmarshal
../cust.xml
輸入如下:
姓名:李俊
證件號碼:210106421016001
性別:男
出生地:大連
國籍:中 國
學歷:高 中
郵政編碼:116001
電話號碼:2645677
5.2 Marshal Java對象到XML文件
把數據從Java Object的形式轉換為XML文件是Unmarshal的逆過程,在語義上用的也是Marshal(解碼)這一名詞。下面提供的例子(例4)提供一個數據綁定使用完整的例子:
將Cust.xml讀入
Unmarshal XML
修改Java對象的屬性值
Marshal Java對象
package com.zjh.zeustest;
import java.io.*;
import com.zjh.zeustest.binding.*;
public class CustomerMarshal
{
public static void
main(String[] args)
{
if(args.length!=1)
{
System.out.println
("please in put the location of XML file");
return;
}
try{
Customer customer =
CustomerUnmarshaller.unmarshal
((new File(args[0])),false);
Contact_Info contactInfo
= customer.getContact_Info();
contactInfo.setId("0002");
contactInfo.setZip_Code("116001");
contactInfo.setTel_No("6656456");
customer.setBirth_Date("1979-10-1");
customer.setBirth_Place("大連");
customer.setContact_Info(contactInfo);
customer.setCustomer_No("1234566");
customer.setEducation("大學");
customer.setId_No("210204197910012233");
customer.setName("李明");
customer.setNationality("中國");
customer.setSex("男");
customer.marshal((new
File("MarshalCust.xml")));
}catch(Exception e){
e.printStackTrace();
}
}
}
例4 Marshal JavaObject
執行該程序后生成的新的MarshalCust.xml如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Customer SYSTEM
"D:/zeus/dtd/Customer.dtd">
<Customer Customer_No="1234566">
<Name>李明</Name>
<Id_No>210204197910012233</Id_No>
<Sex>男</Sex>
<Birth_Place>大連</Birth_Place>
<Birth_Date>1979-10-1</Birth_Date>
<Nationality>中國</Nationality>
<Education>大學</Education>
<Contact_Info id="0002">
<Zip_Code>116001</Zip_Code>
<Tel_No>6656456</Tel_No>
</Contact_Info>
</Customer>
選擇Zeus的理由與思考:
Java與XML是一對天生的兄弟,在所有計算機軟件技術都高舉XML大旗的時候,有一萬個理由實現Java與XML的完美結合。Sun、Apache也提供了功能強大XML解析包,站在巨人的肩膀上(實際上Zeus使用了Apache的Xerces來解析XML),Zeus提出的是數據綁定的概念。
從解析到綁定不需要很復雜的實現手法,但卻提供給使用者更加簡單和靈活的解決方案。編程技術的發展和開放軟件的出現為創意提供了更廣闊的空間,選擇Zeus,使用Zeus,思考Zeus--沒有復雜的技術,只有令人贊嘆的創意。這也許就是后軟件時代程序生存的真諦,我想。