Java 中文官方教程 2022 版(四十九)(2)https://developer.aliyun.com/article/1488530
javaType 绑定声明
声明提供了一种自定义将 XML 数据类型转换为 Java 数据类型的方法。XML 提供的数据类型比 Java 更多,因此当默认的 JAXB 绑定无法充分表示您的模式时,
声明使您能够指定自定义数据类型绑定。
目标 Java 数据类型可以是 Java 内置数据类型或特定于应用程序的 Java 数据类型。如果将特定于应用程序的 Java 数据类型用作目标,则您的实现还必须为解组和组合数据提供解析和打印方法。为此,JAXB 规范支持 parseMethod
和 printMethod
:
parseMethod
在解组过程中被调用,将输入文档中的字符串转换为目标 Java 数据类型的值。- 在组合过程中,
printMethod
被调用以将目标类型的值转换为词法表示。
如果您更喜欢定义自己的数据类型转换,JAXB 定义了一个静态类 DatatypeConverter
,以帮助解析和打印 XML Schema 内置数据类型的有效词法表示。
自定义的语法为:
<javaType name= "*javaType*" [ xmlType= "*xmlType*" ] [ hasNsContext = "true" | "false" ] [ parseMethod= "*parseMethod*" ] [ printMethod= "*printMethod*" ]>
name
是要将xmlType
绑定到的 Java 数据类型。xmlType
是要将javaType
绑定到的 XML Schema 数据类型的名称;当声明的父级为
时,此属性是必需的。
hasNsContext
允许指定命名空间上下文作为打印或解析方法的第二个参数;可以是true
、false
、1
或0
。默认情况下,此属性为false
,在大多数情况下,无需更改。parseMethod
是在解组过程中调用的解析方法的名称。printMethod
是在组合过程中调用的打印方法的名称。
声明可用于:
- 一个
声明
- 用于简单类型定义、
GlobalBindings
和声明的注释元素
- 一个
声明
请参见MyDatatypeConverter
类 ,了解在自定义数据类型转换器类中如何实现 声明和
DatatypeConverterInterface
接口的示例。
类型安全枚举绑定声明
类型安全枚举声明提供了一种将 XML simpleType
元素映射到 Java typesafe enum
类的本地化方式。您可以进行两种类型的类型安全枚举声明:
允许您将整个
simpleType
类映射到typesafe enum
类。允许您将
simpleType
类的选定成员映射到typesafe enum
类。
在这两种情况下,对此类型的自定义有两个主要限制:
- 只有具有枚举约束的
simpleType
定义才能使用此绑定声明进行自定义。 - 此自定义仅适用于一次仅有一个
simpleType
定义。要在全局级别映射一组相似的simpleType
定义,请在声明中使用
typesafeEnumBase
属性,如全局绑定声明中所述。
自定义的语法为:
<typesafeEnumClass [ name = "enumClassName" ] [ <typesafeEnumMember> ... </typesafeEnumMember> ]* [ <javadoc> enumClassJavadoc </javadoc> ] </typesafeEnumClass>
name
必须是有效的 Java 标识符,并且不能有包前缀。- 您可以在
声明中嵌入零个或多个
声明。
定制了枚举类的 Javadoc 工具注释。
定制的语法是:
<typesafeEnumMember name = "enumMemberName"> [ value = "enumMemberValue" ] [ <javadoc> enumMemberJavadoc </javadoc> ] </typesafeEnumMember>
name
必须始终指定,并且必须是有效的 Java 标识符。value
必须是源模式中指定的枚举值。定制了枚举常量的 Javadoc 工具注释。
对于内联注释,必须在元素的注释元素中指定
声明。必须在枚举成员的注释元素中指定
。这使得枚举成员可以独立于枚举类进行定制。
有关类型安全枚举设计模式的信息,请参阅Joshua Bloch 的Effective Java Programming在 Oracle Technology Network 上的示例章节。。
javadoc 绑定声明
声明允许您向基于模式的 JAXB 包、类、接口、方法和字段添加自定义 Javadoc 工具注释。请注意,
声明不能全局应用;它们只能作为其他绑定定制的子元素有效。
定制的语法是:
<javadoc> Contents in <b>Javadoc<\b> format. </javadoc>
或
<javadoc> <<![CDATA[Contents in <b>Javadoc<\b> format ]]> </javadoc>
请注意,应用于包级别的声明中的文档字符串必须包含开放和关闭标签;例如:
<jxb:package name="primer.myPo"> <jxb:javadoc> <![CDATA[<body> Package level documentation for generated package primer.myPo. </body>]]> </jxb:javadoc> </jxb:package>
定制命名空间前缀
所有标准的 JAXB 绑定声明必须以映射到 JAXB 命名空间 URI java.sun.com/xml/ns/jaxb
的命名空间前缀为前缀。例如,在此示例中,使用了jxb:
。为此,您想要使用标准 JAXB 绑定声明自定义的任何模式必须在模式文件的顶部包含 JAXB 命名空间声明和 JAXB 版本号。例如,在 Customize Inline 示例的po.xsd
中,命名空间声明如下:
<xsd:schema xmlns:xsd= "http://www.w3.org/2001/XMLSchema" xmlns:jxb= "http://java.sun.com/xml/ns/jaxb" jxb:version="1.0">
具有jxb
命名空间前缀的绑定声明采用以下形式:
<xsd:annotation> <xsd:appinfo> <jxb:globalBindings *binding declarations* /> <jxb:schemaBindings> ... *binding declarations* . ... </jxb:schemaBindings> </xsd:appinfo> </xsd:annotation>
请注意,在此示例中,globalBindings
和schemaBindings
声明用于分别指定全局范围和模式范围的定制。这些定制范围在范围、继承和优先级中有更详细的描述。
内联定制示例
Customize Inline 示例演示了通过内联注释对名为po.xsd
的 XML 模式进行的一些基本定制。此外,该示例实现了一个自定义数据类型转换器类MyDatatypeConverter.java
,展示了处理自定义数据类型转换的定制中的打印和解析方法。
总结这个示例:
po.xsd
是一个包含内联绑定定制的 XML 模式。MyDatatypeConverter.java
是一个 Java 类文件,实现了po.xsd
中自定义中指定的打印和解析方法。
Main.java
是自定义内联示例中的主要类文件,使用了由 JAXB 编译器生成的模式派生类。
使用 Ant 构建和运行自定义内联示例
要使用 Ant 编译和运行自定义内联示例,在终端窗口中,转到 jaxb-ri-install/samples/inline-customize/
目录并输入以下内容:
ant
此示例中的关键自定义和自定义的 MyDatatypeConverter.java
类在下一节中有更详细的描述。
自定义模式
在自定义内联示例中使用的自定义模式位于文件 jaxb-ri-install/samples/inline-customize/po.xsd
中。自定义内容位于 标签中。
全局绑定声明
以下代码示例显示了 po.xsd
中的 globalBindings
声明:
<jxb:globalBindings fixedAttributeAsConstantProperty="true" collectionType="java.util.Vector" typesafeEnumBase="xsd:NCName" choiceContentProperty="false" typesafeEnumMemberName="generateError" bindingStyle="elementBinding" enableFailFastCheck="false" generateIsSetMethod="false" underscoreBinding="asCharInWord"/>
在此示例中,除了 collectionType
外,所有值都设置为默认值。
- 将
fixedAttributeAsConstantProperty
设置为 true 表示所有固定属性应绑定到 Java 常量。默认情况下,固定属性映射到更合适的简单属性或集合属性。 - 将
collectionType
设置为java.util.Vector
指定生成实现类中所有列表在内部表示为向量。请注意,您为collectionType
指定的类名必须实现java.util.List
并且可以通过newInstance
调用。 - 如果将
typesafeEnumBase
设置为xsd:string
,这是一种全局方式,指定所有直接或间接从xsd:string
派生并具有枚举约束的simple
类型定义默认绑定到typesafe enum
。如果将typesafeEnumBase
设置为空字符串 (""
),则不会将任何simple
类型定义默认绑定到typesafe enum
类。typesafeEnumBase
的值可以是除xsd:boolean
和两种二进制类型之外的任何原子简单类型定义。 - JAXB 实现不支持
enableFailFastCheck
属性。
- 注意: 使用类型安全的枚举类使您能够将模式枚举值映射到 Java 常量,这样就可以对 Java 常量进行比较,而不是对字符串值进行比较。
模式绑定声明
以下代码显示了 po.xsd
中的模式绑定声明:
<jxb:schemaBindings> <jxb:package name="primer.myPo"> <jxb:javadoc> <![CDATA[<body> Package level documentation for generated package primer.myPo. </body>]]> </jxb:javadoc> </jxb:package> <jxb:nameXmlTransform> <jxb:elementName suffix="Element"/> </jxb:nameXmlTransform> </jxb:schemaBindings>
指定
primer.myPo
作为生成模式派生类的包。指定所有生成的 Java 元素接口默认附加
Element
到生成的名称。例如,当针对此模式运行 JAXB 编译器时,将生成元素接口CommentElement
和PurchaseOrderElement
。相比之下,没有此自定义, 默认绑定会生成Comment
和PurchaseOrder
。如果模式在不同的符号空间中使用相同的名称,例如在全局元素和类型定义中,此自定义可帮助您解决冲突,而不必使用单独的绑定声明逐个解决每个冲突。指定了
primer.myPo
包的自定义 Javadoc 工具注释。请注意,与在类级别显示的声明不同,当在包级别进行
声明时,必须包含开头和结尾的标签。
类绑定声明
以下代码显示了po.xsd
中的类绑定声明:
<xsd:complexType name="PurchaseOrderType"> <xsd:annotation> <xsd:appinfo> <jxb:class name="POType"> <jxb:javadoc> A <b>Purchase Order</b> consists of addresses and items. </jxb:javadoc> </jxb:class> </xsd:appinfo> </xsd:annotation> <!-- ... --> </xsd:complexType>
为基于模式的POType
类编写的 Javadoc 工具注释将包含描述"一个<b>采购订单</b>包括地址和商品。"
其中<
用于转义 HTML 标签中的开括号。
注意: 当在complexType
定义的appinfo
元素中指定自定义时,如前面的示例所示,
complexType
定义将绑定到 Java 内容接口。
在po.xsd
中,另一个自定义在此类级别声明,但这次使用
CDATA
转义 HTML 字符串:
<xsd:annotation> <xsd:appinfo> <jxb:class> <jxb:javadoc> <![CDATA[ First line of documentation for a <b>USAddress</b>.]]> </jxb:javadoc> </jxb:class> </xsd:appinfo> </xsd:annotation>
注意: 如果要在自定义中包含 HTML 标签,必须将数据放在
CDATA
部分中或使用<
转义所有左尖括号。有关更多信息,请参阅XML 1.0 第 2 版。
属性绑定声明
这里特别感兴趣的是generateIsSetMethod
自定义,它导致生成两个额外的属性方法,isSetQuantity
和unsetQuantity
。这些方法使客户端应用程序能够区分模式默认值和在实例文档中明确出现的值。
例如,在po.xsd
中:
<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" default="10"> <xsd:annotation> <xsd:appinfo> <jxb:property generateIsSetMethod="true"/> </xsd:appinfo> </xsd:annotation> <!-- ... --> </xsd:complexType> </xsd:element> </xsd:sequence> </xsd:complexType>
@generateIsSetMethod
适用于quantity
元素,该元素绑定到Items.ItemType
接口中的属性。在Items.ItemType
接口中生成了unsetQuantity
和isSetQuantity
方法。
MyDatatypeConverter
类
类jaxb-ri-install/samples/inline-customize/src/inlinecustomize/primer/MyDatatypeConverter
,如下例所示,提供了一种自定义将 XML 数据类型与 Java 数据类型之间的转换的方法,使用自定义。
package primer; import java.math.BigInteger; import javax.xml.bind.DatatypeConverter; public class MyDatatypeConverter { public static short parseIntegerToShort(String value) { BigInteger result = DatatypeConverter.parseInteger(value); return (short)(result.intValue()); } public static String printShortToInteger(short value) { BigInteger result = BigInteger.valueOf(value); return DatatypeConverter.printInteger(result); } public static int parseIntegerToInt(String value) { BigInteger result = DatatypeConverter.parseInteger(value); return result.intValue(); } public static String printIntToInteger(int value) { BigInteger result = BigInteger.valueOf(value); return DatatypeConverter.printInteger(result); } };
以下代码显示了如何在 po.xsd
中的 声明中引用
MyDatatypeConverter
类:
<xsd:simpleType name="ZipCodeType"> <xsd:annotation> <xsd:appinfo> <jxb:javaType name="int" parseMethod="primer.MyDatatypeConverter.parseIntegerToInt" printMethod="primer.MyDatatypeConverter.printIntTo Integer" /> </xsd:appinfo> </xsd:annotation> <xsd:restriction base="xsd:integer"> <xsd:minInclusive value="10000"/> <xsd:maxInclusive value="99999"/> </xsd:restriction> </xsd:simpleType>
在此示例中,jxb:javaType
绑定声明覆盖了此类型的默认 JAXB 绑定为 java.math.BigInteger
。对于 Customize Inline 示例,ZipCodeType
的限制(特别是有效的美国邮政编码限于五位数字)使得所有有效值都可以适应 Java 基本数据类型 int
。还要注意,因为 在
ZipCodeType
中声明,所以该定制适用于所有引用此 simpleType
定义的 JAXB 属性,包括 getZip
和 setZip
方法。
DataType Converter 示例
DataType Converter 示例类似于 Customize Inline 示例。与 Customize Inline 示例一样,DataType Converter 示例中的定制是通过在应用程序的 XML 模式 po.xsd
中使用内联绑定声明来实现的。
Customize Inline 和 DataType Converter 示例的全局、模式和包以及大多数类自定义是相同的。DataType Converter 示例与 Customize Inline 示例不同之处在于用于将 XML 数据转换为 Java int
数据类型的 parseMethod
和 printMethod
。
具体而言,DataType Converter 示例不是使用自定义的 MyDataTypeConverter
类中的方法执行这些数据类型转换,而是使用 javax.xml.bind.DatatypeConverter
提供的内置方法:
<xsd:simpleType name="ZipCodeType"> <xsd:annotation> <xsd:appinfo> <jxb:javaType name="int" parseMethod="javax.xml.bind.DatatypeConverter.parseInt" printMethod="javax.xml.bind.DatatypeConverter.printInt"/> </xsd:appinfo> </xsd:annotation> <xsd:restriction base="xsd:integer"> <xsd:minInclusive value="10000"/> <xsd:maxInclusive value="99999"/> </xsd:restriction> </xsd:simpleType>
使用 Ant 构建和运行 DataType Converter 示例
要使用 Ant 编译和运行 DataType Converter 示例,在终端窗口中,转到 jaxb-ri-install/samples/datatypeconverter/
目录,并输入以下内容:
ant
绑定声明文件
以下各节提供有关绑定声明文件的信息:
- JAXB 版本、命名空间和模式属性
- 全局和模式绑定声明
- 类声明
JAXB 版本、命名空间和模式属性
所有 JAXB 绑定声明文件必须以以下内容开头:
- JAXB 版本号
- 命名空间声明
- 模式名称和节点
bindings.xjb
中的版本、命名空间和模式声明如下:
<jxb:bindings version="1.0" > <jxb:bindings schemaLocation="po.xsd" node="/xs:schema"> <!-- ... *binding-declarations* ... --> </jxb:bindings> <!-- schemaLocation="po.xsd" node="/xs:schema" --> </jxb:bindings>
Java 中文官方教程 2022 版(四十九)(4)https://developer.aliyun.com/article/1488541