简述
不过在展开 JAXB 的讨论之前,我要简要地回顾一下本系列 上一篇文章中所提到的概念。其中的重要定义有:
解组:把 XML 数据转化成 Java 类(或者多个类)的过程。
编组:把 Java 数据转化成 XML 文档的过程(恰恰与解组相反)。
语义等价:基于 XML 规则的相等。即使两个文档 看起来不同,但在语义上可能是等价的,参见上一篇文章中的例子。
往返:从 XML 文档到 Java 代码然后再回到 XML 的整个过程。有效的往返保证输入和输出文档是相同的(语义等价)。
本文中将不那么严格地使用这些术语,一定要真正掌握每个概念的含义。
还应该明白,本文以及后面的几篇文章中,重点不一定是讨论基本的功能,而使这种功能的实现。煤中数据绑定工具包都能编组和解组数据。但是许多工具包不那么严格地执行这项任务,结果危害了往返的语义等价性。实现中的瑕疵(或者实现的功能不完整)是本系列中开始几篇文章的重点,因此我要用几篇文章来说明工具包的基本用法就不奇怪了,如果不知道它是否 真正有效, 使用一个工具包又有什么意义呢?
最后,我假设您已经安装并运行了 JAXB。您可以在 developerWorks上找到详细描述安装过程的大量文章,而且有了新的 Sun Java Web Services Developer Toolkit,安装非常简单。安装好工具包并设置正确的类路径,就万事俱备了。
回页首
生成类
使用 JAXB 进行之前,首先要生成表示 XML 数据的 Java 类。这些例子中将使用一个非常简单的 XML 文档,如清单 1 所示。这是一份吉他的简单列表,吉他是我的爱好之一。
清单 1. 简单的 XML 文档:吉他列表
<guitars>
<guitar id="10021">
<builder luthier="true">Ryan</builder>
<model>Mission Grand Concert</model>
<back-sides>Brazilian Rosewood</back-sides>
<top>Adirondack Spruce</top>
<notes>
<![CDATA[
Just unbelievable... this guitar has all the tone &
resonance you could ever want. I mean, <<WOW!!!>> This
is a lifetime guitar.
]]>
</notes>
</guitar>
<guitar id="0923">
<builder smallShop="true">Bourgeois</builder>
<model>OMC</model>
<back-sides>Bubinga</back-sides>
<top>Adirondack Spruce</top>
</guitar>
<guitar id="11091">
<builder>Martin & Company</builder>
<model>OM-28VR</model>
<back-sides>Indian Rosewood</back-sides>
<top bearclaw="true">Sitka Spruce</top>
<notes>It's certainly true that Martin isn't the only game in town anymore.
Still, the OM-28VR is one of their best models... and this one
has some fabulous bearclaw to boot. Nice specimen of a
still-important guitar manufacturer.
</notes>
</guitar>
</guitars>
使用 JAXB 时还需要一个 XML Schema 以生成类和数据结构。 清单 1的 XML Schema 如清单 2 所示。
清单 2. 清单 1 的 XML Schema
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xs:element name="back-sides" type="xs:string"/>
<xs:element name="builder">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="luthier" default="false">
<xs:simpleType>
<xs:restriction base="xs:NMTOKEN">
<xs:enumeration value="true"/>
<xs:enumeration value="false"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="smallShop" default="false">
<xs:simpleType>
<xs:restriction base="xs:NMTOKEN">
<xs:enumeration value="true"/>
<xs:enumeration value="false"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element name="guitar">
<xs:complexType>
<xs:sequence>
<xs:element ref="builder"/>
<xs:element ref="model"/>
<xs:element ref="back-sides"/>
<xs:element ref="top"/>
<xs:element ref="notes" minOccurs="0"/>
</xs:sequence>
<xs:attribute name="id" type="xs:string" use="required"/>
</xs:complexType>
</xs:element>
<xs:element name="guitars">
<xs:complexType>
<xs:sequence>
<xs:element ref="guitar" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="model" type="xs:string"/>
<xs:element name="notes" type="xs:string"/>
<xs:element name="top">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="bearclaw" default="false">
<xs:simpleType>
<xs:restriction base="xs:NMTOKEN">
<xs:enumeration value="true"/>
<xs:enumeration value="false"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:schema>
回页首
基本步骤
准备好了 XML 和 XML Schema,生成 JAXB 类就很简单了。确认已设置好命令行和环境,然后输入以下命令:
xjc -p com.ibm.dw guitars.xsd -d src
一定要在和 guitars.xsd文件相同的目录中执行上述命令,并且在工作目录中建立一个 src目录。如果没有按这些步骤操作,就会出现某种 java.io.IOException 错误。否则应该能看到一长串的输出结果,如清单 3 所示。
清单 3. JAXB 类生成的输出结果
C:\developerworks>xjc -p com.ibm.dw guitars.xsd -d src
parsing a schema...
compiling a schema...
com\ibm\dw\impl\runtime\MSVValidator.java
com\ibm\dw\impl\runtime\SAXUnmarshallerHandlerImpl.java
com\ibm\dw\impl\runtime\ErrorHandlerAdaptor.java
com\ibm\dw\impl\runtime\AbstractUnmarshallingEventHandlerImpl.java
com\ibm\dw\impl\runtime\UnmarshallableObject.java
com\ibm\dw\impl\runtime\SAXMarshaller.java
com\ibm\dw\impl\runtime\XMLSerializer.java
com\ibm\dw\impl\runtime\ContentHandlerAdaptor.java
com\ibm\dw\impl\runtime\UnmarshallingEventHandlerAdaptor.java
com\ibm\dw\impl\runtime\SAXUnmarshallerHandler.java
com\ibm\dw\impl\runtime\ValidatorImpl.java
com\ibm\dw\impl\runtime\ValidatableObject.java
com\ibm\dw\impl\runtime\UnmarshallerImpl.java
com\ibm\dw\impl\runtime\NamespaceContext2.java
com\ibm\dw\impl\runtime\Discarder.java
com\ibm\dw\impl\runtime\NamespaceContextImpl.java
com\ibm\dw\impl\runtime\ValidatingUnmarshaller.java
com\ibm\dw\impl\runtime\UnmarshallingContext.java
com\ibm\dw\impl\runtime\GrammarInfoImpl.java
com\ibm\dw\impl\runtime\ValidationContext.java
实在是有点太多了--注意,即使对于一个相当简单的 XML Schema,JAXB 也创建了 大量的类。
回页首
对往返的影响
现在我已经介绍了基本的步骤,下面将实际分析一下其中到底发生了什么。不必浪费时间回顾 JAXB 的基础(其他文章已经做了很好的介绍),对于每个元素都有两个源文件,一个文件和元素同名(比如,Guitar.java),另一个则在元素名后面加上“Type”(如 GuitarType.java)。这两个文件都是接口,类的实现在子目录 impl 下。这样就生成了很多类--我认为有点太过分了。
但真正有意思的是这些类本身。要知道数据绑定实现的主要问题之一是往返--即从 XML 到 Java 代码再返回到 XML 的过程中数据不会发生不可预料的变化的能力。换句话说,进去的是什么出来的就是什么。在目前,您还没有准备好通过解组-编组循环测试输出的结果(尽管以后要这样做),首先来分析源代码中可能存在的潜在问题。
第一个问题出现在任何数据绑定软件包通常都会出问题的地方:类型化。即使有 XML Schema 的帮助,XML 也不一定能和 Java 类型很好的匹配。这通常意味着要损失一些数据类型信息,有可能掺入非法的数据。有时候问题出在 XML Schema 中,有时候则是因为 XML 到 Java 映射的局限性,必须仔细观察。源代码中发现的一个此类问题是 top 元素的表示。注意清单 4 中粗体显示的那一行,这是 TopType 类的源代码。
清单 4. TopType.java 的源代码
package com.ibm.dw;
public interface TopType {
java.lang.String getValue();
void setValue(java.lang.String value);
java.lang.String getBearclaw();
void setBearclaw(java.lang.String value);
}
回头再看一看源文档及其 XML Schema,很明显 bearclaw 属性的值应该是“true”或“false”。不幸的是,JAXB 没有发现这一点并使用布尔数据类型, TopType 类的这个属性可以接受任何字符串值。结果可能造成错误的数据。最终可能出现“True”、“true”、“tRUe”或者任何其他变化形式,而令使用 XML 的应用程序举止失措。换句话说,您碰到了必须解决的一个问题域。
这类问题可能有以下不同的解决办法:
手工编辑 TopType 类的源代码,只接受布尔值。
向 TopType 方法中手工添加异常处理代码,保证只能提供可以转化成布尔值的字符串。
在 XML Schema 中创建表达布尔数据类型的新类型。
前两种选择非常明显。第三种选择也很简单,尽管 W3C 那帮人实际上应该把这一条放在规范中说明。清单 5 给出了一个简单的布尔类型定义:
清单 5. 模式中的布尔类型
<xsd:simpleType name="xsd:boolean">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="true"/>
<xsd:enumeration value="True"/>
<xsd:enumeration value="TRUE"/>
<xsd:enumeration value="false"/>
<xsd:enumeration value="False"/>
<xsd:enumeration value="FALSE"/>
</xsd:restriction>
</xsd:simpleType>
看起来不错,是吧?但问题是它还不能解决这个问题。JAXB 根据 XML Schema 中 xsd:string 构造的用法,仍然会生成接受字符串参数的类。
在您准备告诉我这不成为一个问题之前,先让我说明 JAXB 通过 什么来保护您的数据。当从 Java 类编组回到 XML 时,将调用根据 XML Schema(和限制性的类型,如 清单 2和 清单 5所示)生成的验证方法。换句话说,如果您为 bearclaw 属性提供了一个值“foobar”,它就会被找出来。不过像“TRUe”、“fAlSe”和“tRue”这样的值--当然也不想要这种结果--在验证过程中也会被找出来。现在就需要使用 清单 5中详细定义的类型, 还要注意“true”和“false”这两个词因为大小写带来的变化。这种繁杂的工作看起来意义不大。正是这类问题使得往返非常复杂,真正实现要比说起来困难得多。这也 恰恰是在选择和使用数据绑定软件包时应该考虑到的那类问题。
更加需要关注的是,至少对我而言,这样可能造成超出单次往返过程的问题。要知道错误检查只有在编组时进行,这意味着只要还在内存中,错误数据就可以自由地存在于这些成员变量之中等待编组。另外, 任何具有有限值集的性质都存在这种问题,而不仅仅是布尔值。但其中最值得注意的问题是,有时候 XML 文档被读入、处理然后供其他应用程序使用,而不是被编组回到 XML。因此所有的应用程序都有可能在这些字段中插入错误的数据,而其他任何使用数据的应用程序都会得到那个错误数据。除非希望每次访问信息时都编组类,否则这个问题就确实存在。顺便说一句,这些问题表明数据绑定相对而言还不够成熟,而不仅仅是 JAXB。
回页首
我该怎么做?
那么您能做什么呢?首先要坚持阅读这些文章。我将详细分析 JAXB,后面还将探讨 Castor,尝试标志出那些需要注意的地方。不知道问题的关键在哪里,就不能编写防弹代码和错误检查代码;这正是本文以及后面几篇文章的核心。更重要的是,要认识到即使最好的数据绑定软件包,也需要一两个很棒的程序员增加另外的保护措施,才能使其正确地运行。
最后还要记住,数据绑定并不总是魔法子弹。我并不想打消你们对数据绑定的兴趣,恰恰相反,我认为它是一种了不起的应用程序。但是有时候一个简单的 SAX 程序或者 DOM 树就能提供需要的全部功能,就不需要再引入数据绑定项目的复杂性了。在以后的专栏中,我将分析使用数据绑定的最佳时机,什么时候使用 SAX 和 DOM 更有效,并通过大量的例子帮助您作出决策。
回页首
结束语
显然这里关于 JAXB 的分析还不够完全,但是您已经看到了研究数据绑定软件包时有价值的分析方法。选择一个数据绑定软件包要比选择喜欢的网站和单击链接复杂得多,要保证选择的应用程序能够正确处理像往返这样的问题。
JAXB 仍然不够成熟,仍然是一种非常新的技术的较早主要版本。还要记住 JAXB 以前的几个版本基本上已经废弃了(还记得当时 JAXB 只能使用 DTD 吗?它现在只能使用 XSD),因此 1.x 版是对这类问题真正的 第一次尝试。并不说不应使用 JAXB,只是说必须小心谨慎。
下一篇文章,我将从类生成转移到解组和编组,并说明它是如何工作的。我还将钻研像空格、CDATA 节以及许多其他问题的处理。请继续坚持,您将看到更多的代码、更多的细节和更多的乐趣。下一次网上见!
参考资料
您可以参阅本文在 developerWorks 全球站点上的 英文原文.
阅读本系列文章的 第一篇。
访问 Brett McLaughlin 主持的 developerWorks“ XML 和 Java 技术”论坛,可以找到关于这两种技术的其他信息。
看一看 Brett 关于数据绑定的彻底研究, Java and XML Data Binding (O'Reilly & Associates)。在 developerWorks Developer Bookstore上还可以找到大量其他关于 XML 的书籍。
通过 Daniel Steinberg 的教程“ 使用 JAXB 进行数据绑定”( developerWorks,2003 年 5 月),学习使用数据绑定把存储在 XML 文档中的数据映射到 Java 对象然后再回到 XML。
通过 Dennis Sosnoski 的文章“ 数据绑定,第 1 部分:代码生成方法 — JAXB 及其它”( developerWorks,2003 年 1 月),看一看使用从 XML 文档的 W3C XML Schema 或 DTD 生成的代码实现 XML 数据绑定的几种方法。
从 Jakarta 通用软件包获得文本解析工具。
从 Sun 的站点获得 Sun 的 XML API工具。
通过 Tilak Mitra 的 这篇文章( developerWorks,2004 年 2 月)了解如何使用 WebSphere Studio Application Developer V5.1 开发企业级应用程序。
在 developerWorks XML和 Java 技术专区可以找到更多的数据绑定资源。
了解如何才能成为一名 IBM 认证的 XML 及相关技术的开发人员。
关于作者
Brett McLaughlin 从 Logo 时代(还记得那个小三角吗?)就开始从事计算机。他目前专门使用 Java 相关技术构建应用程序基础设施。他最近几年为 Nextel Communications 和 Allegiance Telecom, Inc. 实现了这些基础设施。Brett 是 Java Apache 项目 Turbine 的缔造者之一,该项目使用 Java servlet 为 Web 应用程序开发建立了可重用的组件体系结构。他还参与了 EJBoss 项目(一种开放源代码的 EJB 应用程序服务器)和 Cocoon(一种开放源代码的 XML Web 发布引擎)。
分享到:
相关推荐
2. **jaxb1-impl.jar**:这是早期版本的JAXB实现,用于将Java对象和XML文档进行相互转换。它包含了运行时需要的类和接口,以便开发者可以将Java类映射到XML Schema,然后进行序列化和反序列化操作。 3. **jaxb-api....
1. **XML Schema到Java类的生成**:用户可以导入XML Schema文件(.xsd),然后利用JAXB插件自动生成对应的Java类,这些类包含了解析和生成XML所需的所有元数据。 2. **Java类到XML的转换**:将已有的Java对象转换成...
1. **数据绑定**: 这是JAXB的核心功能,通过使用`@XmlRootElement`、`@XmlElement`等注解,可以将Java类和XML元素进行绑定。这样,当Java对象被 marshalled(序列化)时,会生成对应的XML文档;当XML文档被...
**JAXB(Java Architecture for XML Binding)** 是Java平台中用于XML到Java对象绑定的API,它是Java EE和Java SE标准的一部分,允许开发者在Java应用程序中方便地将XML数据转换为Java对象,反之亦然。这个过程极大...
`jaxb1-impl.jar`和`jaxb1-impl-src.zip`可能是针对JAXB 1.x版本的实现和源代码,与JAXB 2.x的`jaxb-impl.jar`有所不同,主要用于兼容旧版本的系统或代码。 `jaxb-api-doc.zip`可能包含JAXB API的文档,这对于理解...
1. **jaxb-api.jar**:这是JAXB2的主要API接口定义,包含了所有的注解和接口,如`@XmlRootElement`、`@XmlElement`等,以及用于转换的核心类,如`Unmarshaller`和`Marshaller`。这个jar文件提供了与XML绑定的基本...
`jaxb-api`和`jaxb-impl`是JAXB框架的核心组成部分。这两个JAR文件在处理XML到Java对象的绑定过程中扮演着关键角色。 1. **jaxb-api.jar**: 这个库包含了JAXB API,即Java接口和抽象类,定义了JAXB的工作方式。它...
JAXB(Java Architecture for XML Binding)是Java SE的一部分,它允许开发者将XML文档和Java对象之间进行映射,实现XML数据的编解码。在Java 8中,JAXB是标准库的一部分,但自Java 9起,它被移出核心库,成为可选...
jaxb-2_1_9.zip jaxb最新版本 转:http://blog.sina.com.cn/s/blog_5ce5700e0100bowu.html 使用MyEclipse5.5+jboss-5.0.0.CR1+JDK1.6,在启动时报了一个错误: java.lang.LinkageError: JAXB 2.0 API is being ...
`jaxb-impl.jar`是Java Architecture for XML Binding (JAXB)的一个实现包,它是Java平台标准版(Java SE)和企业版(Java EE)的一部分,主要用于XML到Java对象的绑定以及反之,使得开发者能够方便地在Java程序中...
JAXB是Java SE和Java EE平台的标准部分,它提供了一种将XML文档与Java对象之间进行自动转换的方法,从而简化了XML数据处理。 **JAXB API** `jaxb-api-2.1.jar` 包含了JAXB规范定义的接口和抽象类,它是JAXB实现的...
2. **效率**:由于JAXB是Java平台的标准部分,其性能通常优于许多第三方XML处理库。 3. **易用性**:JAXB提供了一套简洁的API,使得XML操作变得简单直观。 **在实际开发中的应用:** 1. **Web服务**:JAXB常用于...
在Java开发中,JAXB...1. 反序列化时,确保使用正确的编码读取XML文件。 2. 序列化时,指定正确的编码,使生成的XML文件符合预期的编码格式。 遵循这些原则,可以有效地避免在Java开发中使用JAXB时出现的乱码问题。
JAXB是Java SE和Java EE的一部分,对于处理XML数据的Java应用程序来说,它是一个非常重要的工具。 **JAXB 2.2.7** 版本是JAXB的一个特定发行版,可能包含了对之前版本的一些错误修复、性能优化和新功能。由于没有...
1. **绑定(Binding)**:JAXB通过绑定文件(一般为.xjb或绑定注解)将XML Schema(XSD)或者Java类与Java类结构关联起来。这个过程创建了一个Java类模型,其中每个XML元素和属性都对应Java类的字段或方法。 2. **...
1. **@XmlType**: 这个注解用于定义类的属性在XML输出中的顺序。在`WriterXml`类中,propOrder 属性指定了"id", "name", "age", "book"这四个属性的输出顺序。如果未指定,JAXB将以自然顺序处理属性。 2. **@...
1. **Java SE 9+支持**:JAXB 2.3.0开始支持Java 9及其后续版本,这包括模块化系统(Jigsaw)的集成。 2. **API增强**:可能包含了新的API接口或方法,以提供更丰富的功能和更好的用户体验。 3. **性能优化**:可能...
1. **Java类到XML映射(Java Class to XML Mapping)**:JAXB允许你定义Java类,并通过注解或XML绑定(binding)文件将其与XML Schema定义的元素和类型关联。当Java对象被序列化时,它们会被转换为相应的XML结构。 ...
JAXB2.1是JAXB的第二个主要版本,它为开发者提供了更强大、更灵活的功能,以处理XML文档的序列化和反序列化。 **一、JAXB2.1的主要功能** 1. **自动代码生成**:JAXB2.1引入了更强的代码生成能力,可以自动生成...