帝国软件
  设为首页 加入收藏 关于我们
 
解密帝国网站管理系统
栏 目:
 
您的位置:首页 > 技术文档 > JAVA编程 >
Zeus实现XML-JAVA的数据绑定
作者:未知 发布时间:2005-03-12 来源:JSP天空网
内容:

ZEUS 简介
预备知识
编译你的Zeus
生成描述XML的Java对象
Marshal与Unmarshal--XML与JAVA Object的转换
选择Zeus的理由与思考
参考资料
关于作者

钟家豪 (judson78@yahoo.com.cn)

2003 年 3 月

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">
<Zip_Code>116001</Zip_Code>
<Tel_No>2645677</Tel_No>
</Contact_Info>
</Customer>






例1:描述Customer的XML文件

这段XML结构很清晰:描述的是一个"顾客"实体,这个实体有其属性:姓名、身份证号、性别、出生地、生日、出生地、联系方式(邮编、电话)等。

第一行<?xml version="1.0" encoding="GBK"?>表述此XML文件的版本是1.0,用的是"GBK"的编码方式(如果要解析中文,GBK或GB2312是必须的)。<Customer Customer_No= "00001></Customer>组成该文件完整的"根标记",Customer_No是Customer标记的"属性",<Name></Name>、<Nationality></Nationality>是<Customer>的子标记。而在< Contact></Contact>中还可以继续包含子标记:<Zip_Code>、<Tel_No>。用户自定义tag的XML语言给了用户足够的自由度表示数据,但是也为显示和解析带来了难度,为了解决这一问题,W3C在格式控制和标记定义上对XML加以限制。例如<customer></Customer>就是一对不合格的标记。

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。可以在Zeuslib下找到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的所有源代码,并将之放置于buildclasses下;
bin:将原srcin下的文件拷到buildin下,原lib目录下的jar文件拷到buildlib下并将组合好的zeus.jar置于此文件夹下;
doc:编译javadoc,并将结果拷到bindocsapidoc下。



sample和test分别用于编译例程和测试代码。如果不想一步一步编译,可以将targers参数设为all,这样ant就会以正确的次序为你自动编译好所有的targets。编译后的会出现一个build文件夹,所有编译好的文件都在这个文件中。检查build/bin文件夹,出现的Zeus.jar文件就是编译好的工具。如果你有足够的经验去修改Zeus的源代码和build.xml文件,完全可以打造属于你自己的Zeus。

4 生成描述XML的Java对象
生成Java对象的第一步是使用Zeus自动生成Java源代码。使用zeus的批处理文件在buildin的zeus.bat,使用语法如下:




zeus.bat -constraints=
[-outputDir=]
[-collapseSimpleElements=]
[-ignoreIDAttributes=]
[-javaPackage=]
[-root=]




参数解释如下:

参数 必须 默认值 描 述
Constraints Yes 无 指定产生java代码的约束文件(dtd或xsd.文件)
OutputDir No 当前目录 放置生成java文件的根目录
CollapseSimpleElements No False 是否支持简单元素的精简,所谓"简单元素"就是在DTD文件中描述的没有属性(attribute)的元素(Element)。如果这样的简单元素以"精简"形式被Zeus解析,则生成的Java类使用其父元素的get[ElementName]()的形式来得到XML中该元素的值,这种形式比普通的get[ElementName]().getContent()的形式更简便。而且减少了很多不必要的生成类。
IgnoreIDAttributes No False 此参数设定判断"简单元素"的条件:是否将ID属性作为条件。设定此参数为true会导致那些只有一个"id"属性的元素被看作是"简单元素"
JavaPackage No 无 指定生成的java类的包。例如:指定com.zjh.tools后,所有生成的java类都在com.zjh.tools包内。
Root No 由DTD解析器决定 确定用于解析的根元素。解析有多个顶级元素的DTD文件时,指定根元素使之生成正确的java类。



继续上面的例子,将例1的XML文件与Java Objects绑定,第一步要生成Java文件,具体方案就是使用Zeus.jar中的org.enhydra.zeus.util.DTDSourceGenerator,例2中的Customer.dtd文件作为必须的constrains参数。首先执行下列命令:

将Customer文件置于c:zeusdtd文件下,建立c:zeuszjhsample,执行下列命令:
C:zeus>.uildinzeus.bat -constraints=dtdCustomer.dtd -outputDir=zjhsample -javaPackage =com.zjh.zeustest.binding -collapseSimpleElements=true

查看c:zeuszjhsamplecomzjhzeustestinding文件夹,发现生成了六个文件: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 .;..libxerces.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:zeusdtdCustomer.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--没有复杂的技术,只有令人赞叹的创意。这也许就是后软件时代程序生存的真谛,我想。

关于作者
钟家豪,目前在中国广东从事金融领域的软件开发,主要致力于J2EE架构、XML、WebService和数据库方面的研究。可以通过 judson78@yahoo.com.cn 与他联系。
  
评论】【加入收藏夹】【 】【打印】【关闭
※ 相关链接
无相关信息

   栏目导行
  PHP编程
  ASP编程
  ASP.NET编程
  JAVA编程
   站点最新
·致合作伙伴的欢迎信
·媒体报道
·帝国软件合作伙伴计划协议
·放眼未来 帝国近期将有重大举措!
·PHPWind6.3.2版通行证发布
·帝国备份王2008版正式发布
·帝国备份王2008版发布
·phpcms2007转帝国CMS5.0程序发布
·dedecms5.1转帝国CMS5.0程序发布
·帝国网站管理系统V5.0商业购买说明
   类别最新
·谈谈JDBC
·JDBC专题介绍
·JDBC接口技术
·利用weblogic的POOL(连接池)连接
·Jsp中调用Oracle存储过程的小例子
·JSP数据库操作例程
·JSP数据库连接大全
·用连接池提高Servlet访问数据库的效
·一种简单JDBC连接池的实现
·数据库连接池Java实现小结
 
关于帝国 | 广告服务 | 联系我们 | 程序开发 | 网站地图 | 留言板 帝国网站管理系统