文档

Java™ 教程
隐藏目录
Java到模式的示例
导航: Java Architecture for XML Binding (JAXB)
课程: JAXB简介

Java到模式示例

Java-to-Schema示例演示了如何使用注解将Java类映射到XML模式。

j2s-create-marshal示例

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.xsdschemagen不允许您指定自定义模式名称。

使用Ant构建和运行j2s-create-marshal示例

要使用Ant编译和运行j2s-create-marshal示例,在终端窗口中,进入jaxb-ri-install/samples/j2s-create-marshal/目录,然后输入以下命令:

ant 

j2s-xmlAccessorOrder示例

j2s-xmlAccessorOrder示例演示了如何使用@XmlAccessorOrder@XmlType.propOrder注解来指定Java类型进行编组和解组时的XML内容顺序。

在Java-to-schema映射中,JavaBean的属性和字段被映射到XML模式类型。类元素被映射到XML模式复杂类型或XML模式简单类型。生成的模式类型的默认元素顺序目前未指定,因为Java反射不会强制返回顺序。缺乏可靠的元素顺序对应用程序的可移植性产生负面影响。您可以使用两个注解@XmlAccessorOrder@XmlType.propOrder来定义跨JAXB提供程序必须具备可移植性的应用程序的模式元素顺序。

使用@XmlAccessorOrder注解定义模式元素顺序

@XmlAccessorOrder注解强制执行两种元素顺序算法,AccessorOrder.UNDEFINEDAccessorOrder.ALPHABETICALAccessorOrder.UNDEFINED是默认设置。顺序取决于系统的反射实现。AccessorOrder.ALPHABETICAL算法按字典顺序排列元素,由java.lang.String.CompareTo(String anotherString)确定。

您可以在类对象上为注解类型ElementType.PACKAGE定义@XmlAccessorOrder注解。当@XmlAccessorOrder注解定义在包上时,格式规则的范围对包中的每个类都有效。当在类上定义时,该规则对该类的内容有效。

在一个包中可以有多个@XmlAccessorOrder注解。最内层(类)注解优先于外部注解。例如,如果在包上定义了@XmlAccessorOrder(AccessorOrder.ALPHABETICAL),并且在该包中的类上定义了@XmlAccessorOrder(AccessorOrder.UNDEFINED),则该类的生成模式类型的内容将是未指定顺序,而该包中其他每个类的生成模式类型的内容将按字母顺序排列。

使用@XmlType注解定义模式元素顺序

可以为一个类定义@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定义了@XmlAccessorOrderALPHABETICAL,适用于该包。类PurchaseOrderType中的公共字段shipTobillTo受到该规则影响,生成的模式内容顺序受到影响。类USAddress在类上定义了@XmlType.propOrder注解,演示了用户定义的属性顺序优先于生成的模式中的ALPHABETICAL顺序。

生成的模式文件可以在jaxb-ri-install/samples/j2s-xmlAccessorOrder/build/schemas/目录中找到。

使用Ant构建和运行j2s-xmlAccessorOrder示例

要使用Ant编译和运行j2s-xmlAccessorOrder示例,在终端窗口中,进入jaxb-ri-install/samples/j2s-xmlAccessorOrder/目录,然后输入以下命令:

ant 

j2s-xmlAdapter示例

j2s-xmlAdapter示例演示了如何使用XmlAdapter接口和@XmlJavaTypeAdapter注解,将XML内容自定义映射到使用int作为键和String作为值的HashMap(字段)中。

XmlAdapter接口和@XmlJavaTypeAdapter注解用于在取消编组和编组过程中对数据类型进行特殊处理。有各种XML数据类型的表示形式不易映射到Java(例如xs:DateTimexs: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类型、PACKAGEFIELDMETHODTYPEPARAMETER关联。

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类PurchaseListPartEntry,它们反映了解组和组合内容的所需模式。这些类生成的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示例

要使用Ant编译和运行j2s-xmlAdapter示例,在终端窗口中,进入jaxb-ri-install/samples/j2s-xmlAdapter/目录,然后输入以下内容:

ant

j2s-xmlAttribute示例

j2s-xmlAttribute示例展示了如何使用@XmlAttribute注解来定义一个属性或字段作为XML属性。

@XmlAttribute注解将字段或JavaBean属性映射到XML属性。遵循以下规则:

按照JavaBean编程范例,属性由字段名前缀getset定义。

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示例

要使用Ant编译和运行j2s-xmlAttribute示例,在终端窗口中,进入jaxb-ri-install/samples/j2s-xmlAttribute/目录,然后输入以下内容:

ant

j2s-xmlRootElement 示例

j2s-xmlRootElement 示例演示了使用@XmlRootElement注解来为对应类的XML模式类型定义XML元素名称。

@XmlRootElement注解将一个类或枚举类型映射到一个XML元素。对于每个用于取消编组和编组的顶级Java类型,至少需要一个元素定义。如果没有元素定义,则没有XML内容处理的起始位置。

@XmlRootElement注解使用类名作为默认元素名称。您可以使用注解属性name更改默认名称。如果这样做,指定的名称将用作元素名称和类型名称。元素和类型名称不同是常见的模式实践。您可以使用@XmlType注解来设置元素类型名称。

@XmlRootElement注解的命名空间属性用于为元素定义命名空间。

使用Ant构建和运行j2s-xmlRootElement示例

要使用Ant编译和运行j2s-xmlRootElement示例,在终端窗口中,转到jaxb-ri-install/samples/j2s-xmlRootElement/目录,然后输入以下命令:

ant

j2s-xmlSchemaType 示例

j2s-xmlSchemaType 示例演示了使用注解@XmlSchemaType自定义属性或字段与XML内置类型的映射。

@XmlSchemaType注解可用于将Java类型映射到XML内置类型之一。此注解在将Java类型映射到九种日期/时间原始数据类型之一时最有用。

当在包级别定义@XmlSchemaType注解时,标识需要XML内置类型名称和相应的Java类型类。字段或属性上的@XmlSchemaType定义优先于包定义。

XmlSchemaType Class 示例展示了如何在包级别、字段和属性上使用@XmlSchemaType注解。文件TrackingOrder有两个字段orderDatedeliveryDate,它们被定义为XMLGregorianCalendar类型。生成的模式将定义这些元素为XML内置类型gMonthDay。这个关系在package-info.java文件中在包上定义。文件TrackingOrder中的shipDate字段也被定义为XMLGregorianCalendar类型,但@XmlSchemaType注解语句覆盖了包定义,并指定该字段为date类型。属性方法getTrackingDuration定义模式元素为原始类型duration,而不是Java类型String

使用Ant构建和运行j2s-xmlSchemaType示例

使用Ant编译和运行j2s-xmlSchemaType示例,在终端窗口中,进入jaxb-ri-install/samples/j2s-xmlSchemaType/目录,然后输入以下命令:

ant 

j2s-xmlType示例

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示例

使用Ant编译和运行j2s-xmlType示例,在终端窗口中,进入jaxb-ri-install/samples/j2s-xmlType/目录,然后输入以下命令:

ant

上一页:自定义JAXB绑定
下一页:更多信息