使用JAXB将XML Schema绑定到Java类
Java Architecture for XML Binding (JAXB) 是一项可以根据XML 模式产生Java类的Java技术。该过程中,JAXB也提供了将XML实例文档反编组到Java内容树的方法,并能将Java内容树编组回XML实例文档。从另一方面来讲,JAXB提供了快速而简便的方法将XML模式绑定到Java表示,从而使得Java开发者在Java应用程序中能方便地结合XML数据和处理函数。
这意味着你不需要处理甚至不需要知道XML编程技巧就能在Java应用程序中利用平台核心XML数据的灵活性。而且,可以充分利用XML的优势而不用依赖于复杂的XML处理模型如SAX或DOM。JAXB 隐藏了细节并且取消了SAX和DOM中没用的关系——生成的JAXB类仅描述原始模型中定义的关系。其结果是结合了高度可移植Java代码的高度可移植的XML数据,其中这些代码可用来创建灵活、轻便的应用程序和Web服务。
本章介绍了JAXB体系结构、函数和核心概念。在学习第十章之前必须先阅读本章。第十章给出了示例代码和逐步使用JAXB的过程。
JAXB 体系结构
本节主要讨论JAXB处理模型中的组件和交互。在给出了总的概述之后,本节将详细讨论核心的JAXB特性。本节中的主题主要包括:
体系结构概述
图 9-1 给出了构成JAXB实现的组件。
图 9-1 JAXB体系结构概述
如图9-1所示,JAXB实现包含下列八个核心组件:
表 9-1 JAXB实现中的核心组件
组件
描述
XML Schema
XML模式使用XML语法描述XML文档中元素、属性和实体之间的关系。XML模式的目标是定义一个XML文档类,该类必须坚持特定的结构规则和数据约束。例如,你可能希望给面向章的书、在线采购系统或个人数据库定义不同的模式。在JAXB上下文中,将包含数据的受到XML模式约束的XML文档叫做文档实例,并且将文档实例中的结构和数据叫做内容树
Binding
Declarations
默认情况下,JAXB绑定编译器根据JAXB规范第5节“将XML Schema绑定到Java表示”中定义的规则将Java类和包绑定到原始XML模式。多数情况下,利用默认的规则已经能够从大量的模式中产生一组强壮的模式派生类。但是,有的时候,默认的绑定规则就不够用了。JAXB支持通过绑定声明自定义或覆盖默认的绑定规则。这些绑定声明或者是内部源模式的注释或者是传递给JAXB绑定编译器的外部绑定自定义文件中的语句。注意,自定义的JAXB绑定声明也允许摆脱XML模式中特定于XML的束缚,来自定义生成的JAXB类,以包含特定于Java的改进,如类和包名映射
Binding
Compiler
JAXB绑定编译器是JAXB处理模型的核心。它的功能是将源XML模式转换或绑定到Java编程语言中的一组JAXB内容类。基本上,可以通过将一个XML模式 (可以选择使用自定义绑定声明)用作输入来运行JAXB绑定编译器。绑定编译器产生Java类,这些Java类映射到了源XML 模式中的约束条件
Binding
Framework
Implementation
JAXB绑定框架实现是运行时API,它提供了反编组、编组和验证Java应用程序中的XML内容的接口。绑定框架包括javax.xml.bind 包中的接口
Schema-Derived
Classes
这些是JAXB编译器产生的模式派生类。根据输入的模式将采用不同的类
Java
Application
在JAXB上下文中,Java应用程序是客户端应用程序,它使用JAXB绑定框架来反编组XML数据,验证并修改Java内容对象,并将Java内容编组成XML数据。特别是,JAXB绑定框架包装在一个能提供UI功能、XML转换功能、数据处理或其他所需要的功能的大型Java应用程序中
XML Input
Documents
这是反编组出来用作JAXB绑定框架输入的XML内容——即XML实例文档,从这里将产生内容树形式的Java表示。实际上, 术语“文档”不再是传统意义上的文档了,因为XML实例文档不一定要是形式完整的、自立的文档文件;相反它具有流的形式,这些流可以是应用程序之间传递的数据、数据库字段集合、XML信息集合,其中信息块包含了描述它们在模式结构中的位置的足够信息。
在JAXB中,反编组过程支持根据源模式定义的约束验证XML输入文档。然而该验证过程是可选的,在某些情况下你可能通过其他途径知道输入文档是有效的,出于对性能的考虑你可能选择在反编组过程中跳过验证。但是,无论在哪种情况下,反编组之前(通过第三方应用程序)或之后验证都很重要,这是因为它确保了关于源模式编组过程中产生的XML文档也是有效的。在本章的后面部分将详细介绍验证
XML Output
Documents
这是编组到XML文档的XML内容。在JAXB中,编组包括解析XML内容对象树并写出一个XML文档,该文档是原始XML文档的精确表示并且相对于原始模式来说是有效的。JAXB能够将XML数据编组成XML 文档、SAX内容处理程序和DOM节点。
JAXB绑定过程
图9-2显示了JAXB的绑定过程。
图 9-2 JAXB绑定过程步骤
JAXB数据绑定过程的常用步骤是:
1. 生成类。将XML模式放入JAXB绑定编译器,以产生基于该模式的JAXB类。
2. 编译类。 必须编译所有生成的类、源文件和应用程序代码。
3. 反编组。JAXB绑定框架反编组根据原始模式中的约束编写的XML文档。注意JAXB也支持反编组来自除了文件/文档之外XML数据,如DOM节点、字符串缓冲、SAX Source等等。
4. 生成内容树。 反编组过程产生从生成的JAXB类实例化而来的数据对象内容树,该内容树代表了源XML文档的结构和内容。
5. 验证(可选)。 反编组过程中,可以在生成内容树之前验证源XML文档。注意,如果在第6步中修改内容树,下面,你也能使用JAXB验证操作在将内容编组到XML文档之前验证变化。
6. 处理内容。客户端应用程序通过绑定编译器产生的接口方法可以修改Java内容树表示的XML数据。
7. 编组。将处理过的内容树编组到一个或多个XML输出文档中。在编组之前要验证内容。
总而言之,使用JAXB涉及到两个独立的活动集:
根据源模式生成并编译JAXB类,并且建立一个实现这些类的应用程序。
在JAXB绑定框架中运行应用程序,以反编组、处理、验证和编组XML内容。
通常分时间分阶段执行这两个步骤。典型地,例如,需要在应用程序开发阶段生成并编译JAXB类,并且建立绑定实现,接着是部署阶段,在该阶段使用生成的JAXB类在“现场”产品环境中处理XML内容。
注意:反编组不是创建内容树的唯一的方法。模式派生的内容类通过直接调用合适的工厂方法也支持按计划构建内容树。一旦创建了,任何时候都可以重新验证内容树的一部分或全部。查看示例应用程序 3 中的使用ObjectFactory 类直接给内容树添加内容的例子。
JAXB绑定框架
JAXB绑定框架由三个Java包实现:
javax.xml.bind 包定义直接和内容类一起使用的抽象类和接口。
javax.xml.bind 包定义Unmarshaller、Validator和Marshaller 类,它们是提供各自操作的辅助对象。
JAXBContext 类是Java应用程序到JAXB框架的入口点。JAXBContext 实例为反编组、编组和验证操作使用的JAXB实现将XML元素名绑定到Java内容接口。
javax.xml.bind 包也定义了编组或反编组错误出现时、违反约束时及出现其他类型的错误时使用的丰富的验证事件和异常类的层次结构。
javax.xml.bind.util 包包含工具类,客户端应用程序可以使用它们来管理编组、反编组和验证事件。
javax.xml.bind.helper 包为一些javax.xml.bind 接口提供了部分默认的实现。JAXB的实现能够扩展这些类并且实现抽象方法。使用JAXB体系结构的应用程序不能直接使用这些API。
下面将详细介绍JAXB绑定框架中的主要的包javax.bind.xml。
关于javax.xml.bind的更多信息
主要绑定框架包javax.xml.bind提供的三个核心功能是编组、反编组和验证。到绑定框架的主要的客户端入口点是JAXBContext 类。
JAXBContext 提供了一个抽象,该抽象可以管理实现反编组、编组和验证操作必要的XML/Java绑定信息。客户端应用程序通过newInstance(contextPath)方法得到该类的新实例。例如:
JAXBContext jc = JAXBContext.newInstance(
"com.acme.foo:com.acme.bar" );
contextPath 参数包含一个Java包名,这些包包含模式派生的接口—特别是JAXB绑定编译器产生的接口。该参数值初始化JAXBContext 对象,使得它能够管理模式派生的接口。为此目的,JAXB提供程序实现必须提供一个包含下列特征的实现类:
public static JAXBContext createContext( String contextPath,
ClassLoader classLoader )
throws JAXBException;
注意:在每个包含模式派生类的包中,JAXB提供程序实现必须生成一个jaxb.properties 文件。该属性文件必须包含一个叫做javax.xml.bind.context.factory 的属性,它的值是实现createContext API的类的名字。
不一定要将提供程序提供的类分配给javax.xml.bind.JAXBContext,它只是必须提供一个实现 createContext API的类。允许指定多个Java包,JAXBContext 实例允许同时管理多个模式。
关于反编组的更多信息
javax.xml.bind 包中的Unmarshaller 类使得客户端应用程序能够将XML数据转换成Java内容对象树。模式的unmarshal 方法(在命名空间内)允许将模式中声明的任何全局XML元素反编组成实例文档的根。JAXBContext 对象允许在一组模式内合并全局元素(列在contextPath中)。由于模式集中的每个模式属于不同的命名空间,将模式统一到反编组上下文中是独立于命名空间的。这意味着客户端应用程序能够反编组contextPath 中列出的任何模式的实例XML文档。例如:
JAXBContext jc = JAXBContext.newInstance(
"com.acme.foo:com.acme.bar" );
Unmarshaller u = jc.createUnmarshaller();
FooObject fooObj =
(FooObject)u.unmarshal( new File( "foo.xml" ) ); // ok
BarObject barObj =
(BarObject)u.unmarshal( new File( "bar.xml" ) ); // ok
BazObject bazObj =
(BazObject)u.unmarshal( new File( "baz.xml" ) );
// error, "com.acme.baz" not in contextPath
客户端应用程序也能明显地生成Java内容树而不是反编组现有XML数据。这样做,应用程序必须能够存取并了解contextPath 中的每个Java包中模式派生的ObjectFactory 类。对于每个模式派生Java类,将有一个静态工厂方法能产生该类型的对象。例如,假设编译了模式之后,得到一个包含PurchaseOrder 模式派生接口的包com.acme.foo 。要创建这类对象,客户端应用程序将使用下列工厂方法:
ObjectFactory objFactory = new ObjectFactory();
com.acme.foo.PurchaseOrder po =
objFactory.createPurchaseOrder();
注意:由于当contextPath 上有多个包时,会产生多个ObjectFactory 类,所以如果你有多个contextPath上的包,在引用某个包中的ObjectFactory 类时,必须使用完整的包名。
一旦客户端应用程序有模式派生对象的实例,它就能使用赋值方法来设置它的内容。
注意:JAXB 提供程序实现必须在每个包中生成一个类,这些包包含ObjectFactory 包的必要的对象工厂方法和newInstance( javaContentInterface ) 方法。
关于编组的更多信息
javax.xml.bind 包中的Marshaller 类使得客户端应用程序能够将Java内容树转换成XML数据。编组一个使用工厂方法人为创建的内容树和反编组操作得到的内容树之间没有什么区别。客户端能够将Java内容树编组回到java.io.OutputStream 或java.io.Writer的XML数据中。编组过程能够在注册的ContentHandler 中生成SAX2 事件流或生成DOM Node 对象。
下面是一个简单的例子,它反编组一个XML文档,然后在将它编组回去:
JAXBContext jc = JAXBContext.newInstance( "com.acme.foo" );
// unmarshal from foo.xml
Unmarshaller u = jc.createUnmarshaller();
FooObject fooObj =
(FooObject)u.unmarshal( new File( "foo.xml" ) );
// marshal to System.out
Marshaller m = jc.createMarshaller();
m.marshal( fooObj, System.out );
默认情况下,在java.io.OutputStream 或 java.io.Writer中生成XML数据时,Marshaller使用UTF-8 编码。使用setProperty API 改变编组操作中输出的编码。客户端应用程序提供W3C XML 1.0 推荐中定义的有效的字符编码名(http://www.w3.org/TR/2000/REC-xml-20001006#charencoding) 并且你的Java平台支持它。
在调用编组API之前,不要求客户端应用程序验证Java内容树。同样,也不要求根据源模式验证Java内容树以便将它编组回XML数据。不同的JAXB提供程序支持编组不同层的无效Java内容树,然而,所有的JAXB提供程序必须能够将有效的内容树编组成XML数据。当JAXB提供程序由于无效的内容而不能完成编组操作时必须抛出MarshalException 。一些JAXB提供程序将完全支持编组无效内容,而其他一些将在遇到第一个验证错误后就失效。
表 9-2 列出了Marshaller 类支持的属性
表 9-2 Marshaller 属性
属性
描述
jaxb.encoding
值必须是java.lang.String;这是编组XML数据时使用的输出编码。默认情况下,如果没有指定它的属性,Marshaller 将使用"UTF-8"
jaxb.formatted.output
值必须是java.lang.Boolean。它控制Marshaller 是否使用行分隔和缩进格式化结果XML数据。如果它的值为true 表示易读缩进的XML数据,如果值为false 表示未格式化的XML数据。如果没有指定该属性,Marshaller 的默认值为false (unformatted)
jaxb.schemaLocation
值必须是java.lang.String;它允许客户端应用程序指定生成的XML数据中的xsi:schemaLocation 属性。W3C XML Schema部分0:入门的第5.6节中通过一种易于理解的、非标准的形式介绍了schemaLocation 属性值的格式,并且在W3C XML Schema Part 1:结构 的第2.6节中规定了该属性值的格式
jaxb.noNamespaceSchemaLocation
值必须是java.lang.String;允许客户端应用程序指定生成的XML数据中的xsi:noNamespaceSchemaLocation 属性
关于验证的更多信息
javax.xml.bind 包中的Validator 类主要用来在运行时控制对内容树的验证。当反编组过程结合了验证,并且验证成功,没有产生任何验证错误,那么就能确保输出的文档和结果内容树是有效的。相对比,编组过程中并不进行验证。如果仅仅编组有效的内容树,这就能保证相对于源模式来说,生成的XML文档总是有效的。
一些XML解析器如SAX和DOM允许取消模式验证功能,并且在一些情况下,为了提高处理速度并且/或者为了处理包含无效或不完整的内容的文档,你可能希望取消模式验证。通过在能使用JAXB的应用程序中选泽的异常处理程序,JAXB支持这些处理方案。总的说来,如果一个JAXB实现不能确切完成反编组或编组,它将抛出一个异常,终止处理。
注意:Validator 类负责管理On-Demand验证(如下所示)。Unmarshaller 类负责管理反编组操作中的 Unmarshal-Time 验证。虽然没有正式的方法能够在编组操作中启动验证,Marshaller 可以监测错误,将它报告给它上面注册的ValidationEventHandler 。
JAXB客户端可以实现两类验证:
Unmarshal-Time 验证 使得客户端应用程序能够接收将XML数据反编组到Java内容树时监测到的验证错误消息和警告,并且跟验证的其他类型完全正交。使用Unmarshaller.setValidating方法来启动或终止它。所有的JAXB提供程序都要支持该操作。
On-Demand 验证 使得客户端应用程序能够接收Java内容树中监测到的验证错误和警告。这点上,客户端应用程序能够在Java内容树(或者它的任何子树)上调用Validator.validate 方法。所有的JAXB提供程序都要支持该操作。
如果客户端应用程序没有在调用验证、反编组或编组方法之前就在它的Validator 、Unmarshaller或 Marshaller 上设置事件处理程序,那么默认的事件处理程序将接收遇到的任何错误通知。在遇到第一个错误或致命错误后,默认的事件处理程序将挂起当前操作 (但是在接收到警告后将继续该操作)
有三种方法能够处理反编组、验证和编组操作过程中遇到的事件:
使用默认的事件处理程序。
如果没有通过Validator、Unmarshaller或Marshaller上的setEventHandler API设置事件处理程序,将会使用默认的事件处理程序。
实现并注册一个自定义的事件处理程序。
需要复杂的事件处理的客户端应用程序能够实现ValidationEventHandler 接口并使用Unmarshaller 和/或 Validator注册它。
使用ValidationEventCollector 工具。
为了方便,提供一个特定的事件处理程序,该处理程序仅仅收集反编组、验证和编组操作中创建的ValidationEvent 对象,并且将它们作为java.util.Collection返回给客户端应用程序。
根据客户端应用程序的配置,使用不同的方法来处理验证事件。然而,在一些情况下,JAXB提供程序不能正确地监测并报告错误。在这些情况下,JAXB提供程序将ValidationEvent 的验证性设置成 FATAL_ERROR ,表明将终止反编组、验证和编组操作。在收到致命错误的通知后,默认的事件处理程序和ValidationEventCollector工具类必须终止处理。接收到致命错误的通知后,支持它们自己的ValidationEventHandler 客户端应用程序必须也终止处理。如果不终止处理,将会出现意想不到的情况。
XML Schema
由于XML模式是JAXB处理模型的一个重要的组件——并且由于其他数据绑定性能如JAXP使用DTD而不用模式——因此在这里了解一下XML模式的基本概念和它们的工作原理很有用。
XML Schema是描述XML文档中允许的元素、属性、实体和关系的强大的方法。DTD的一个更加强壮的选择,XML模式的目标是定义XML文档的类,该类必须遵守一组特定的结构和数据约束——也就是说,你可能希望为面向章的书、在线采购系统或个人数据库定义不同的模式。在JAXB上下文中,将包含受到XML模式约束的XML文档称作文档实例,并且将文档实例内部的结构和数据叫做内容树。
注意: 实际上,术语“文档”并不总是精确的,因为XML实例文档不一定要是形式完整的、自立的文档文件;相反它具有流的形式,这些流可以是应用程序之间传递的数据、数据库字段集合、XML信息集合,其中信息块包含了描述它们在模式结构中的位置的足够信息。
下面的例子代码来自于W3C Schema 部分 0:入门(http://www.w3.org/TR/2001/REC-xmlschema-0-20010502/),显示了一个XML文档po.xml,是一个简单的购买订单。
<?xml version="1.0"?>
<purchaseOrder orderDate="1999-10-20">
<shipTo country="US">
<name>Alice Smith</name>
<street>123 Maple Street</street>
<city>Mill Valley</city>
<state>CA</state>
<zip>90952</zip>
</shipTo>
<billTo country="US">
<name>Robert Smith</name>
<street>8 Oak Avenue</street>
<city>Old Town</city>
<state>PA</state>
<zip>95819</zip>
</billTo>
<comment>Hurry, my lawn is going wild!</comment>
<items>
<item partNum="872-AA">
<productName>Lawnmower</productName>
<quantity>1</quantity>
<USPrice>148.95</USPrice>
<comment>Confirm this is electric</comment>
</item>
<item partNum="926-AA">
<productName>Baby Monitor</productName>
<quantity>1</quantity>
<USPrice>39.98</USPrice>
<shipDate>1999-05-21</shipDate>
</item>
</items>
</purchaseOrder>
根元素purchaseOrder包含子元素shipTo, billTo、comment和items。除了comment 之外的所有子元素包含其他子元素。树的叶子是子元素,如name, street、city和state,它们不包含任何子元素。包含其他子元素或能接受属性的元素叫做复合类型。仅包含PCDATA 并且没有子元素的元素叫做简单类型。
下面的采购模式中定义了po.xml 中的复杂类型和一些简单类型。同样,该例子模式来自于W3C Schema 部分 0:入门(http://www.w3.org/TR/2001/REC-xmlschema-0-20010502/).
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="purchaseOrder" type="PurchaseOrderType"/>
<xsd:element name="comment" type="xsd:string"/>
<xsd:complexType name="PurchaseOrderType">
<xsd:sequence>
<xsd:element name="shipTo" type="USAddress"/>
<xsd:element name="billTo" type="USAddress"/>
<xsd:element ref="comment" minOccurs="0"/>
<xsd:element name="items" type="Items"/>
</xsd:sequence>
<xsd:attribute name="orderDate" type="xsd:date"/>
</xsd:complexType>
<xsd:complexType name="USAddress">
<xsd:sequence>
<xsd:element name="name" type="xsd:string"/>
<xsd:element name="street" type="xsd:string"/>
<xsd:element name="city" type="xsd:string"/>
<xsd:element name="state" type="xsd:string"/>
<xsd:element name="zip" type="xsd:decimal"/>
</xsd:sequence>
<xsd:attribute name="country" type="xsd:NMTOKEN"
fixed="US"/>
</xsd:complexType>
<xsd:complexType name="Items">
<xsd:sequence>
<xsd:element name="item" minOccurs="1"
maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="productName"
type="xsd:string"/>
<xsd:element name="quantity">
<xsd:simpleType>
<xsd:restriction base="xsd:positiveInteger">
<xsd:maxExclusive value="100"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="USPrice" type="xsd:decimal"/>
<xsd:element ref="comment" minOccurs="0"/>
<xsd:element name="shipDate" type="xsd:date"
minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="partNum" type="SKU"
use="required"/>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<!-- Stock Keeping Unit, a code for identifying products -->
<xsd:simpleType name="SKU">
<xsd:restriction base="xsd:string">
<xsd:pattern value="\d{3}-[A-Z]{2}"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>
在本例中, 模式同DTD一样包含main或根schema 元素和几个子元素element、complexType和simpleType。和DTD不同,该模式也被指定成属性数据类型,如decimal、 date、 fixed和string。模式也受到如pattern value、 minOccurs和positiveInteger的约束。在DTD中,只能指定文本数据(PCDATA 和CDATA)的数据类型, XML模式支持更加复杂的文本和数值数据类型和约束,这些在Java语言中都有直接对应部分。
注意,本模式中的每个元素都有前缀xsd:,它和W3C XML Schema 命名空间相关。为此,命名空间声明,xmlns:xsd="http://www.w3.org/2001/XMLSchema", 声明的是schema 元素的一个属性。
支持命名空间是XML Schema的另一个重要的特征,因为它为区分根据不同模式书写的元素提供了一个方法或有其他不同的用途,但是它们可能和文档中的其他元素有相同的名字。例如,假设你在你的模式中定义两个命名空间,一个是 foo ,另外一个是bar。结合两个XML 文档,一个来自于开账单数据库,另一个来自于运送数据库,每个都建立在不同的模式下。通过在模式中指定命名空间,你可以区分foo:address 和bar:address。
表示XML内容
本节介绍JAXB 如何将XML内容表示成Java对象。本节主题如下:
将XML名字绑定到Java标识符
XML模式语言使用XML名字——与XML1.0(第二版本) (http://www.w3.org/XML/)中定义的用来标识模式组件的名字产品匹配的字符串。该字符串集合比有效的Java类、方法和约束标识符的集合大。要解决该差异,JAXB使用几个名字-映射算法。
JAXB名字-映射算法根据标准Java API设计指南将XML名字映射到Java标识符,生成保留了到相应模式连接的标识符,并且不太可能产生冲突。
参考第10章,查看如何改变默认XML名字映射。查看JAXB规范附录C中关于JAXB命名算法的完整细节。
XML模式的Java表示
JAXB支持组合Java包中生成的类和接口。一个包包括:
· 名字,直接来自于XML命名空间URI或由XML命名空间URI绑定自定义指定。
· 一组Java内容接口,表示模式中声明的内容模型。
· 一组Java元素接口,表示模式中出现的元素声明。
· 包含如下内容的一个ObjectFactory 类:
o 每个Java内容接口的实例工厂方法和包中的Java元素接口,例如,给定一个叫做Foo的Java内容接口,取得的工厂方法是:
public Foo createFoo() throws JAXBException;
o 动态实例工厂分配器,创建指定的Java内容接口的一个实例,例如:
public Object newInstance(Class javaContentInterface)
throws JAXBException;
o getProperty和setProperty API ,它们允许操纵指定提供程序的属性。
· typesafe 枚举类集合
· 包 javadoc
绑定XML Schema
本节介绍了JAXB使用的默认的XML-到-Java绑定。通过自定义绑定声明可以通过自定义的绑定声明全局覆盖或逐层覆盖所有这些绑定。本节主题如下:
· 简单类型定义
查看JAXB 规范[/url] ,以获得JAXB绑定的完整信息。
简单类型定义
使用简单类型定义的模式组件通常和Java 属性绑定。由于有多种这类模式组件,下列Java特征属性(在模式组件中很常见)包括:
· 基本类型
· 集合类型,如果有的话
· 谓词
其他Java特征属性是使用simple 类型定义在模式组件中指定的。
默认的数据类型绑定
Java语言提供了比XML模式更加丰富的数据类型集。[url=http://gceclub.sun.com.cn/staticcontent/html/webservices/web_services_tutorial/9/9.1.htm#wp86708]表 9-3 列出了XML数据类型到JAXB中的Java数据类型的映射。
表 9-3 XML模式内置数据类型的JAXB映射
XML Schema 类型
Java数据类型
xsd:string
java.lang.String
xsd:integer
java.math.BigInteger
xsd:int
int
xsd.long
long
xsd:short
short
xsd:decimal
java.math.BigDecimal
xsd:float
float
xsd:double
double
xsd:boolean
Boolean
xsd:byte
byte
xsd:Qname
javax.xml.namespace.QName
xsd:dateTime
java.util.Calendar
xsd:base64Binary
byte[]
xsd:hexBinary
byte[]
xsd:unsignedInt
long
xsd:unsignedShort
int
xsd:unsignedByte
short
xsd:time
Java.util.Calendar
xsd:date
Java.util.Calendar
xsd:anySimpleType
Java.lang.String
默认的绑定规则摘要
JAXB绑定模型遵守下列默认的绑定规则:
· 将下列内容绑定到Java包:
o XML 命名空间URI
· 将下列XML模式组件绑定到Java内容接口:
o 命名的复杂类型
o 元素声明中匿名的内部类型定义
· 绑定到类型安全枚举类:
o 一个命名的简单类型定义,它有来自"xsd:NCName" 的基本类型,并且有枚举面。
· 将下列XML Schema组件绑定到Java Element接口:
o Element 接口的全局元素声明
o 能够插入到全局内容列表的本地元素声明
· 绑定到Java属性:
o 使用的属性
o 元素引用或本地元素声明的术语微粒
· 将重复出现和复杂的类型定义的模型组和混合的{content type} 绑定到:
o 通用内容属性; 具有Java实例表示元素信息项和字符数据项的列表内容属性 。
自定义JAXB绑定
使用自定义的绑定声明可以在全局范围或逐层地覆盖默认的JAXB绑定。如前面所介绍的,JAXB 使用默认的绑定规则,可以通过下面两种方法可以自定义这些绑定规则:
· 源XML模式的内部注释
· 传递给JAXB绑定编译器的外部绑定自定义文件中的声明
自定义JAXB绑定声明也能不受XML schema中的XML规范约束自定义生成的JAXB类,让它包括特定于Java改进,如类和包名映射。
你不需要为模式中的每个声明提供一个绑定指令来生成Java类。例如,绑定编译器使用通用的名字影射算法将XML名字绑定到Java编程语言能够接受的名字。然而,如果在类中想要使用不同的名字模式,你可以明确自定义绑定声明让绑定编译器生成不同的名字。在绑定声明中可以进行许多其他自定义,包括:
· 命名包、衍生类和方法
· 给衍生类中的方法分配类型
· 选择将哪个元素绑定到类
· 确定如何将属性和元素声明绑定到适当内容类的属性
· 选择每个属性值或内容规范的类型
注意: 依赖于默认的JAXB绑定行为而不是为Java表示的每个XML Schema组件作出绑定声明使得它能够方便地跟上源模式中的变化。在多数情况下, 默认的规则非常强壮,所以不需要任何自定义的绑定声明就能产生可用的绑定。
第10章中给出了自定义JAXB绑定的代码例子。
作用域
当在绑定声明中定义自定义值时,就涉及到作用域。自定义值的作用域就是应用它的模式元素集合。如果将一个自定义值应用到一个模式元素,那么该模式元素就在自定义值的作用域内。
表 9-4 列出了自定义的绑定的四个作用域。
表9-4 自定义绑定的作用域
作用域
描述
Global
<globalBindings> 中定义的自定义值具有全局作用域。全局作用域覆盖了源模式中的所有模式元素和(递归的)源模式中包括或导入的任何模式
Schema
<schemaBindings> 中定义的自定义值具有模式作用域。模式作用域覆盖了模式的目标命名空间的所有模式元素
Definition
类型定义的绑定声明中的自定义值和全局声明具有定义作用域。定义作用域覆盖了引用类型定义或全局声明的所有模式元素
Component
如果自定义值仅应用到绑定声明注释的模式元素,绑定声明中的自定义值具有组件作用域
作用域继承
不同的作用域形成了一个分类系统。该分类系统定义了自定义值的继承和覆盖语义。一个作用域内的自定义值被另一个作用域的绑定声明继承使用,下面是继承的层次关系:
· 模式作用域内的模式元素继承全局作用域内定义的自定义值。
· 定义作用域内的模式元素继承模式或全局作用域内定义的自定义值。
· 组件作用域内的模式元素继承定义、模式 或全局作用域内定义的自定义值。
相似的,一个作用域内的自定义值能够覆盖继承自另一个作用域的自定义值,如下所示:
· 模式作用域内的值覆盖继承自全局作用域的值。
· 定义作用域内的值覆盖继承自模式作用域或全局作用域的值。
· 组件作用域的值覆盖继承自定义、模式或全局作用域的值。
哪些是不支持的
查看JAXB规范的第E.2节“非必需的XML Schema概念”,获得未得到支持的或非必需的模式概念的最新信息。
JAXB API 和工具
JAXB API和工具在Java WSDP的jaxb-1.0 子目录中。该目录包括一组简单应用程序、javadoc API文档、JAXB绑定编译器(xjc)、javax.xml.bind 包中包含的运行绑定框架API的实现。如果想知道如何使用JAXB,请查看第10章。