Java 教程是为 JDK 8 编写的。本页中描述的示例和实践未利用在后续版本中引入的改进。
The Java-to-Schema examples show how to use annotations to map Java classes to XML schema.
The j2s-create-marshal example illustrates Java-to-schema data binding. It demonstrates marshalling and unmarshalling of JAXB annotated classes and also shows how to enable JAXP 1.3 validation at unmarshal time using a schema file that was generated from the JAXB mapped classes.
The schema file, bc.xsd, was generated with the following commands:
schemagen src/cardfile/*.java cp schema1.xsd bc.xsd
Note that schema1.xsd was copied to bc.xsd; schemagen does not allow you to specify a schema name of your choice.
To compile and run the j2s-create-marshal example using Ant, in a terminal window, go to the jaxb-ri-install/samples/j2s-create-marshal/ directory and type the following:
ant
The j2s-xmlAccessorOrder example shows how to use the @XmlAccessorOrder and @XmlType.propOrder annotations to dictate the order in which XML content is marshalled and unmarshalled by a Java type.
With Java-to-schema mapping, a JavaBean’s properties and fields are mapped to an XML Schema type. The class elements are mapped to either an XML Schema complex type or an XML Schema simple type. The default element order for a generated schema type is currently unspecified because Java reflection does not impose a return order. The lack of reliable element ordering negatively impacts application portability. You can use two annotations, @XmlAccessorOrder and @XmlType.propOrder, to define schema element ordering for applications that must be portable across JAXB Providers.
The @XmlAccessorOrder annotation imposes one of two element ordering algorithms, AccessorOrder.UNDEFINED or AccessorOrder.ALPHABETICAL. AccessorOrder.UNDEFINED is the default setting. The order is dependent on the system’s reflection implementation. AccessorOrder.ALPHABETICAL algorithm orders the elements in lexicographic order as determined by java.lang.String.CompareTo(String anotherString).
You can define the @XmlAccessorOrder annotation for annotation type ElementType.PACKAGE on a class object. When the @XmlAccessorOrder annotation is defined on a package, the scope of the formatting rule is active for every class in the package. When defined on a class, the rule is active on the contents of that class.
There can be multiple @XmlAccessorOrder annotations within a package. The innermost (class) annotation takes precedence over the outer annotation. For example, if @XmlAccessorOrder(AccessorOrder.ALPHABETICAL) is defined on a package and @XmlAccessorOrder(AccessorOrder.UNDEFINED) is defined on a class in that package, the contents of the generated schema type for the class would be in an unspecified order and the contents of the generated schema type for every other class in the package would be in alphabetical order.
The @XmlType annotation can be defined for a class. The annotation element propOrder() in the @XmlType annotation enables you to specify the content order in the generated schema type. When you use the @XmlType.propOrder annotation on a class to specify content order, all public properties and public fields in the class must be specified in the parameter list. Any public property or field that you want to keep out of the parameter list must be annotated with @XmlAttribute or @XmlTransient annotation.
The default content order for @XmlType.propOrder is {} or {""}, not active. In such cases, the active @XmlAccessorOrder annotation takes precedence. When class content order is specified by the @XmlType.propOrder annotation, it takes precedence over any active @XmlAccessorOrder annotation on the class or package. If the @XmlAccessorOrder and @XmlType.propOrder(A, B, ...) annotations are specified on a class, the propOrder always takes precedence regardless of the order of the annotation statements. For example, in the following code segment, the @XmlAccessorOrder annotation precedes the @XmlType.propOrder annotation.
@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;} // ... }
In the following code segment, the @XmlType.propOrder annotation precedes the @XmlAccessorOrder annotation.
@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;} // ... }
In both scenarios, propOrder takes precedence and the following identical schema content is generated:
<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>
The purchase order code example demonstrates the effects of schema content ordering using the @XmlAccessorOrder annotation at the package and class level, and the @XmlType.propOrder annotation on a class.
Class package-info.java defines @XmlAccessorOrder to be ALPHABETICAL for the package. The public fields shipTo and billTo in class PurchaseOrderType are affected in the generated schema content order by this rule. Class USAddress defines the @XmlType.propOrder annotation on the class which demonstrates user-defined property order superseding ALPHABETICAL order in the generated schema.
The generated schema file can be found in the jaxb-ri-install/samples/j2s-xmlAccessorOrder/build/schemas/ directory.
To compile and run the j2s-xmlAccessorOrder example using Ant, in a terminal window, go to the jaxb-ri-install/samples/j2s-xmlAccessorOrder/ directory and type the following:
ant
The j2s-xmlAdapter example demonstrates how to use the XmlAdapter interface and the @XmlJavaTypeAdapter annotation to provide a custom mapping of XML content into and out of a HashMap (field) that uses an int as the key and a String as the value.
Interface XmlAdapter and annotation @XmlJavaTypeAdapter are used for special processing of data types during unmarshalling and marshalling. There are a variety of XML data types for which the representation does not map easily into Java (for example, xs:DateTime and xs:Duration), and Java types that do not map properly into XML representations. For example, implementations of java.util.Collection (such as List) and java.util.Map (such as HashMap) or for non-JavaBean classes.
The XmlAdapter interface and the @XmlJavaTypeAdapter annotation are provided for cases such as these. This combination provides a portable mechanism for reading and writing XML content into and out of Java applications.
The XmlAdapter interface defines the methods for data reading and writing.
/* * ValueType - Java class that provides an * XML representation of the data. * It is the object that is used for marshalling and * unmarshalling. * * BoundType - Java class that is used to * process XML content. */ public abstract class XmlAdapter<ValueType,BoundType> { // Do-nothing constructor for the derived classes. protected XmlAdapter() {} // Convert a value type to a bound type. public abstract BoundType unmarshal(ValueType v); // Convert a bound type to a value type. public abstract ValueType marshal(BoundType v); }
You can use the @XmlJavaTypeAdapter annotation to associate a particular XmlAdapter implementation with a Target type, PACKAGE, FIELD, METHOD, TYPE, or PARAMETER.
The j2s-xmlAdapter example shows how to use an XmlAdapter for mapping XML content into and out of a (custom) HashMap. The HashMap object, basket, in class KitchenWorldBasket, uses a key of type int and a value of type String. These data types should be reflected in the XML content that is read and written, so the XML content should look as in the following example:
<basket> <entry key="9027">glasstop stove in black</entry> <entry key="288">wooden spoon</entry> </basket>
The default schema generated for Java type HashMap does not reflect the desired format.
<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>
In the default HashMap schema, key and value are both elements and are of data type anyType. The XML content looks like the following:
<basket> <entry> <key>9027</key> <value>glasstop stove in black</value> </entry> <entry> <key>288</key> <value>wooden spoon</value> </entry> </basket>
To resolve this issue, the example uses two Java classes, PurchaseList and PartEntry, that reflect the needed schema format for unmarshalling and marshalling the content. The XML schema generated for these classes is as follows:
<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>
Class AdapterPurchaseListToHashMap implements the XmlAdapter interface. In class KitchenWorldBasket, the @XmlJavaTypeAdapter annotation is used to pair AdapterPurchaseListToHashMap with the field HashMap basket. This pairing causes the marshal or unmarshal method of AdapterPurchaseListToHashMap to be called for any corresponding marshal or unmarshal action on KitchenWorldBasket.
To compile and run the j2s-xmlAdapter example using Ant, in a terminal window, go to the jaxb-ri-install/samples/j2s-xmlAdapter/ directory and type the following:
ant
The j2s-xmlAttribute example shows how to use the @XmlAttribute annotation to define a property or field to be treated as an XML attribute.
The @XmlAttribute annotation maps a field or JavaBean property to an XML attribute. The following rules are imposed:
When following the JavaBean programming paradigm, a property is defined by a get and set prefix on a field name.
int zip; public int getZip(){return zip;} public void setZip(int z){zip=z;}
Within a bean class, you have the choice of setting the @XmlAttribute annotation on one of three components: the field, the setter method, or the getter method. If you set the @XmlAttribute annotation on the field, the setter method must be renamed or there will be a naming conflict at compile time. If you set the @XmlAttribute annotation on one of the methods, it must be set on either the setter or getter method, but not on both.
The XmlAttribute example shows how to use the @XmlAttribute annotation on a static final field, on a field rather than on one of the corresponding bean methods, on a bean property (method), and on a field that is other than a collection type. In class USAddress, fields, country, and zip are tagged as attributes. The setZip method was disabled to avoid the compile error. Property state was tagged as an attribute on the setter method. You could have used the getter method instead. In class PurchaseOrderType, field cCardVendor is a non-collection type. It meets the requirement of being a simple type; it is an enum type.
To compile and run the j2s-xmlAttribute example using Ant, in a terminal window, go to the jaxb-ri-install/samples/j2s-xmlAttribute/ directory and type the following:
ant
The j2s-xmlRootElement example demonstrates the use of the @XmlRootElement annotation to define an XML element name for the XML schema type of the corresponding class.
The @XmlRootElement annotation maps a class or an enum type to an XML element. At least one element definition is needed for each top-level Java type used for unmarshalling and marshalling. If there is no element definition, there is no starting location for XML content processing.
The @XmlRootElement annotation uses the class name as the default element name. You can change the default name by using the annotation attribute name. If you do, the specified name is used as the element name and the type name. It is common schema practice for the element and type names to be different. You can use the @XmlType annotation to set the element type name.
The namespace attribute of the @XmlRootElement annotation is used to define a namespace for the element.
To compile and run the j2s-xmlRootElement example using Ant, in a terminal window, go to the jaxb-ri-install/samples/j2s-xmlRootElement/ directory and type the following:
ant
The j2s-xmlSchemaType example demonstrates the use of the annotation @XmlSchemaType to customize the mapping of a property or field to an XML built-in type.
The @XmlSchemaType annotation can be used to map a Java type to one of the XML built-in types. This annotation is most useful in mapping a Java type to one of the nine date/time primitive data types.
When the @XmlSchemaType annotation is defined at the package level, the identification requires both the XML built-in type name and the corresponding Java type class. An @XmlSchemaType definition on a field or property takes precedence over a package definition.
The XmlSchemaType Class example shows how to use the @XmlSchemaType annotation at the package level, on a field, and on a property. File TrackingOrder has two fields, orderDate and deliveryDate, which are defined to be of type XMLGregorianCalendar. The generated schema will define these elements to be of XML built-in type gMonthDay. This relationship was defined on the package in the file package-info.java. Field shipDate in file TrackingOrder is also defined to be of type XMLGregorianCalendar, but the @XmlSchemaType annotation statements override the package definition and specify the field to be of type date. Property method getTrackingDuration defines the schema element to be defined as primitive type duration and not Java type String.
To compile and run the j2s-xmlSchemaType example using Ant, in a terminal window, go to the jaxb-ri-install/samples/j2s-xmlSchemaType/ directory and type the following:
ant
The j2s-xmlType example demonstrates the use of the @XmlType annotation. The @XmlType annotation maps a class or an enum type to an XML Schema type.
A class must have either a public zero-argument constructor or a static zero-argument factory method in order to be mapped by this annotation. One of these methods is used during unmarshalling to create an instance of the class. The factory method can be located within in a factory class or the existing class.
There is an order of precedence as to which method is used for unmarshalling:
In this example, a factory class provides zero arg factory methods for several classes. The @XmlType annotation on class OrderContext references the factory class. The unmarshaller uses the identified factory method in this class.
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() { // ... } } }
In this example, a factory method is defined in a class, which also contains a standard class construct. Because the factoryMethod value is defined and no factoryClass is defined, the factory method newOrderInstance is used during unmarshalling.
@XmlType(name="oContext", factoryMethod="newOrderInstance") public class OrderContext { public OrderContext() { // ... } public OrderContext newOrderInstance() { return new OrderContext(); } }
To compile and run the j2s-xmlType example using Ant, in a terminal window, go to the jaxb-ri-install/samples/j2s-xmlType/ directory and type the following:
ant