本教程适用于JDK 8。本页面中描述的示例和实践不利用后续版本中引入的改进,并可能使用不再可用的技术。
有关Java SE 9及后续版本中更新的语言特性的摘要,请参阅Java语言更改。
有关所有JDK版本的新功能、增强功能和已删除或弃用选项的信息,请参阅JDK发行说明。
Java-to-Schema示例演示了如何使用注解将Java类映射到XML模式。
j2s-create-marshal示例演示了Java-to-schema数据绑定。它演示了对JAXB注解类进行编组和解组,并展示了如何在解组时使用从JAXB映射类生成的模式文件启用JAXP 1.3验证。
模式文件bc.xsd是使用以下命令生成的:
schemagen src/cardfile/*.java cp schema1.xsd bc.xsd
请注意,schema1.xsd被复制到bc.xsd;schemagen不允许您指定自定义模式名称。
要使用Ant编译和运行j2s-create-marshal示例,在终端窗口中,进入jaxb-ri-install/samples/j2s-create-marshal/目录,然后输入以下命令:
ant
j2s-xmlAccessorOrder示例演示了如何使用@XmlAccessorOrder和@XmlType.propOrder注解来指定Java类型进行编组和解组时的XML内容顺序。
在Java-to-schema映射中,JavaBean的属性和字段被映射到XML模式类型。类元素被映射到XML模式复杂类型或XML模式简单类型。生成的模式类型的默认元素顺序目前未指定,因为Java反射不会强制返回顺序。缺乏可靠的元素顺序对应用程序的可移植性产生负面影响。您可以使用两个注解@XmlAccessorOrder和@XmlType.propOrder来定义跨JAXB提供程序必须具备可移植性的应用程序的模式元素顺序。
@XmlAccessorOrder注解强制执行两种元素顺序算法,AccessorOrder.UNDEFINED或AccessorOrder.ALPHABETICAL。AccessorOrder.UNDEFINED是默认设置。顺序取决于系统的反射实现。AccessorOrder.ALPHABETICAL算法按字典顺序排列元素,由java.lang.String.CompareTo(String anotherString)确定。
您可以在类对象上为注解类型ElementType.PACKAGE定义@XmlAccessorOrder注解。当@XmlAccessorOrder注解定义在包上时,格式规则的范围对包中的每个类都有效。当在类上定义时,该规则对该类的内容有效。
在一个包中可以有多个@XmlAccessorOrder注解。最内层(类)注解优先于外部注解。例如,如果在包上定义了@XmlAccessorOrder(AccessorOrder.ALPHABETICAL),并且在该包中的类上定义了@XmlAccessorOrder(AccessorOrder.UNDEFINED),则该类的生成模式类型的内容将是未指定顺序,而该包中其他每个类的生成模式类型的内容将按字母顺序排列。
可以为一个类定义@XmlType注解。在@XmlType注解中的propOrder()元素使你能够指定生成的模式类型中的内容顺序。当你在一个类上使用@XmlType.propOrder注解来指定内容顺序时,类中的所有公共属性和公共字段都必须在参数列表中指定。任何你想要保留在参数列表之外的公共属性或字段必须用@XmlAttribute或@XmlTransient注解标注。
@XmlType.propOrder的默认内容顺序是{}或{""},没有激活。在这种情况下,激活的@XmlAccessorOrder注解优先。当通过@XmlType.propOrder注解指定类的内容顺序时,它优先于类或包上任何激活的@XmlAccessorOrder注解。如果在类上同时指定了@XmlAccessorOrder和@XmlType.propOrder(A, B, ...)注解,无论注解语句的顺序如何,propOrder始终优先。例如,在以下代码段中,@XmlAccessorOrder注解在@XmlType.propOrder注解之前。
@XmlAccessorOrder(AccessorOrder.ALPHABETICAL) @XmlType(propOrder={"name", "city"}) public class USAddress { // ... public String getCity() {return city;} public void setCity(String city) {this.city = city;} public String getName() {return name;} public void setName(String name) {this.name = name;} // ... }
在以下代码段中,@XmlType.propOrder注解在@XmlAccessorOrder注解之前。
@XmlType(propOrder={"name", "city"}) @XmlAccessorOrder(AccessorOrder.ALPHABETICAL) public class USAddress { // ... public String getCity() {return city;} public void setCity(String city) {this.city = city;} public String getName() {return name;} public void setName(String name) {this.name = name;} // ... }
在这两种情况下,propOrder优先,并生成以下相同的模式内容:
<xs:complexType name="usAddress"> <xs:sequence> <xs:element name="name" type="xs:string" minOccurs="0"/> <xs:element name="city" type="xs:string" minOccurs="0"/> </xs:sequence> </xs:complexType>
采购订单代码示例演示了在包和类级别上使用@XmlAccessorOrder注解以及在类上使用@XmlType.propOrder注解时模式内容顺序的影响。
类package-info.java定义了@XmlAccessorOrder为ALPHABETICAL,适用于该包。类PurchaseOrderType中的公共字段shipTo和billTo受到该规则影响,生成的模式内容顺序受到影响。类USAddress在类上定义了@XmlType.propOrder注解,演示了用户定义的属性顺序优先于生成的模式中的ALPHABETICAL顺序。
生成的模式文件可以在jaxb-ri-install/samples/j2s-xmlAccessorOrder/build/schemas/目录中找到。
要使用Ant编译和运行j2s-xmlAccessorOrder示例,在终端窗口中,进入jaxb-ri-install/samples/j2s-xmlAccessorOrder/目录,然后输入以下命令:
ant
j2s-xmlAdapter示例演示了如何使用XmlAdapter接口和@XmlJavaTypeAdapter注解,将XML内容自定义映射到使用int作为键和String作为值的HashMap(字段)中。
XmlAdapter接口和@XmlJavaTypeAdapter注解用于在取消编组和编组过程中对数据类型进行特殊处理。有各种XML数据类型的表示形式不易映射到Java(例如xs:DateTime和xs:Duration),以及无法正确映射到XML表示形式的Java类型。例如,java.util.Collection(如List)和java.util.Map(如HashMap)的实现,或者非JavaBean类。
为了处理这类情况,提供了XmlAdapter接口和@XmlJavaTypeAdapter注解。这个组合提供了一种可移植的机制,用于在Java应用程序中读取和写入XML内容。
XmlAdapter接口定义了数据读取和写入的方法。
/* * ValueType - 提供数据的Java类的XML表示。 * 它是用于编组和取消编组的对象。 * * BoundType - 用于处理XML内容的Java类。 */ public abstract class XmlAdapter<ValueType,BoundType> { // 没有任何操作的构造函数,供派生类使用。 protected XmlAdapter() {} // 将值类型转换为边界类型。 public abstract BoundType unmarshal(ValueType v); // 将边界类型转换为值类型。 public abstract ValueType marshal(BoundType v); }
您可以使用@XmlJavaTypeAdapter注解将特定的XmlAdapter实现与Target类型、PACKAGE、FIELD、METHOD、TYPE或PARAMETER关联。
j2s-xmlAdapter示例展示了如何使用XmlAdapter将XML内容映射到(自定义)HashMap中。类KitchenWorldBasket中的HashMap对象basket使用int类型的键和String类型的值。这些数据类型应该反映在读取和写入的XML内容中,因此XML内容应该如以下示例所示:
<basket> <entry key="9027">黑色玻璃面炉</entry> <entry key="288">木质勺子</entry> </basket>
为Java类型HashMap生成的默认模式不符合所需格式。
<xs:element name="basket"> <xs:complexType> <xs:sequence> <xs:element name="entry" minOccurs="0" maxOccurs="unbounded"> <xs:complexType> <xs:sequence> <xs:element name="key" minOccurs="0" type="xs:anyType"/> <xs:element name="value" minOccurs="0" type="xs:anyType"/> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element>
在默认的HashMap模式中,键和值都是元素,且数据类型为anyType。XML内容如下所示:
<basket> <entry> <key>9027</key> <value>黑色玻璃面炉</value> </entry> <entry> <key>288</key> <value>木质勺子</value> </entry> </basket>
为了解决这个问题,示例使用了两个Java类PurchaseList和PartEntry,它们反映了解组和组合内容的所需模式。这些类生成的XML模式如下:
<xs:complexType name="PurchaseListType"> <xs:sequence> <xs:element name="entry" type="partEntry" nillable="true" maxOccurs="unbounded" minOccurs="0"/> </xs:sequence> </xs:complexType> <xs:complexType name="partEntry"> <xs:simpleContent> <xs:extension base="xs:string"> <xs:attribute name="key" type="xs:int" use="required"/> </xs:extension> </xs:simpleContent> </xs:complexType>
类AdapterPurchaseListToHashMap实现了XmlAdapter接口。在类KitchenWorldBasket中,使用@XmlJavaTypeAdapter注解将AdapterPurchaseListToHashMap与字段HashMap basket配对。这个配对会导致在KitchenWorldBasket上执行相应的marshal或unmarshal操作时调用AdapterPurchaseListToHashMap的marshal或unmarshal方法。
要使用Ant编译和运行j2s-xmlAdapter示例,在终端窗口中,进入jaxb-ri-install/samples/j2s-xmlAdapter/目录,然后输入以下内容:
ant
j2s-xmlAttribute示例展示了如何使用@XmlAttribute注解来定义一个属性或字段作为XML属性。
@XmlAttribute注解将字段或JavaBean属性映射到XML属性。遵循以下规则:
按照JavaBean编程范例,属性由字段名前缀get和set定义。
int zip; public int getZip(){return zip;} public void setZip(int z){zip=z;}
在bean类中,您可以选择在三个组件之一上设置@XmlAttribute注解:字段、setter方法或getter方法。如果在字段上设置@XmlAttribute注解,则必须重新命名setter方法,否则在编译时会出现命名冲突。如果在方法之一上设置@XmlAttribute注解,则必须在setter方法或getter方法上设置,但不能同时在两者上都设置。
XmlAttribute示例展示了如何在静态final字段上、在字段而不是对应的bean方法之一上、在bean属性(方法)上以及在不是集合类型的字段上使用@XmlAttribute注解。在类USAddress中,字段country和zip被标记为属性。为了避免编译错误,禁用了setZip方法。属性state在setter方法上被标记为属性。您也可以使用getter方法。在类PurchaseOrderType中,字段cCardVendor是非集合类型。它满足作为简单类型的要求;它是一个enum类型。
要使用Ant编译和运行j2s-xmlAttribute示例,在终端窗口中,进入jaxb-ri-install/samples/j2s-xmlAttribute/目录,然后输入以下内容:
ant
j2s-xmlRootElement 示例演示了使用@XmlRootElement注解来为对应类的XML模式类型定义XML元素名称。
@XmlRootElement注解将一个类或枚举类型映射到一个XML元素。对于每个用于取消编组和编组的顶级Java类型,至少需要一个元素定义。如果没有元素定义,则没有XML内容处理的起始位置。
@XmlRootElement注解使用类名作为默认元素名称。您可以使用注解属性name更改默认名称。如果这样做,指定的名称将用作元素名称和类型名称。元素和类型名称不同是常见的模式实践。您可以使用@XmlType注解来设置元素类型名称。
@XmlRootElement注解的命名空间属性用于为元素定义命名空间。
要使用Ant编译和运行j2s-xmlRootElement示例,在终端窗口中,转到jaxb-ri-install/samples/j2s-xmlRootElement/目录,然后输入以下命令:
ant
j2s-xmlSchemaType 示例演示了使用注解@XmlSchemaType自定义属性或字段与XML内置类型的映射。
@XmlSchemaType注解可用于将Java类型映射到XML内置类型之一。此注解在将Java类型映射到九种日期/时间原始数据类型之一时最有用。
当在包级别定义@XmlSchemaType注解时,标识需要XML内置类型名称和相应的Java类型类。字段或属性上的@XmlSchemaType定义优先于包定义。
XmlSchemaType Class 示例展示了如何在包级别、字段和属性上使用@XmlSchemaType注解。文件TrackingOrder有两个字段orderDate和deliveryDate,它们被定义为XMLGregorianCalendar类型。生成的模式将定义这些元素为XML内置类型gMonthDay。这个关系在package-info.java文件中在包上定义。文件TrackingOrder中的shipDate字段也被定义为XMLGregorianCalendar类型,但@XmlSchemaType注解语句覆盖了包定义,并指定该字段为date类型。属性方法getTrackingDuration定义模式元素为原始类型duration,而不是Java类型String。
使用Ant编译和运行j2s-xmlSchemaType示例,在终端窗口中,进入jaxb-ri-install/samples/j2s-xmlSchemaType/目录,然后输入以下命令:
ant
j2s-xmlType示例演示了如何使用@XmlType注解。@XmlType注解将类或enum类型映射到XML Schema类型。
类必须具有公共的无参构造函数或静态的无参工厂方法,才能被该注解映射。在解组期间,这些方法之一将用于创建类的实例。工厂方法可以位于工厂类中或现有类中。
以下是用于解组的方法优先级:
在此示例中,工厂类为多个类提供了零参工厂方法。类OrderContext上的@XmlType注解引用了工厂类。解组器将使用该类中标识的工厂方法。
public class OrderFormsFactory { public OrderContext newOrderInstance() { return new OrderContext() } public PurchaseOrderType { newPurchaseOrderType() { return new newPurchaseOrderType(); } } @XmlType(name="oContext", factoryClass="OrderFormsFactory", factoryMethod="newOrderInstance") public class OrderContext { public OrderContext() { // ... } } }
在此示例中,一个类中定义了一个工厂方法,该类还包含一个标准的类构造函数。由于定义了factoryMethod值且未定义factoryClass,因此在解组时将使用工厂方法newOrderInstance。
@XmlType(name="oContext", factoryMethod="newOrderInstance") public class OrderContext { public OrderContext() { // ... } public OrderContext newOrderInstance() { return new OrderContext(); } }
使用Ant编译和运行j2s-xmlType示例,在终端窗口中,进入jaxb-ri-install/samples/j2s-xmlType/目录,然后输入以下命令:
ant