搜索

38.2. 指定 XML 架构 Primitive 的 Java 类

download PDF

概述

默认情况下,XML 架构类型映射到 Java 原语类型。虽然这是 XML 架构和 Java 之间的最逻辑映射,但它并不总是满足应用程序开发人员的要求。您可能希望将 XML 架构原语类型映射到可保存额外信息的 Java 类,或者您可能希望将 XML 原语类型映射到允许简单类型替换的类。

JAXB javaType 自定义元素允许您自定义 XML 架构原语类型和 Java 原语类型之间的映射。它可用于自定义全局级别和单个实例级别的映射。您可以使用 javaType 元素作为简单类型定义的一部分,或作为复杂类型定义的一部分。

在使用 javaType 自定义元素时,您必须指定将 primitive 类型的 XML 表示转换为目标 Java 类的方法。有些映射有默认的转换方法。对于没有默认映射的实例,Apache CXF 提供了 JAXB 方法来简化所需方法的开发。

语法

javaType 自定义元素采用四个属性,如 表 38.1 “为 XML 架构类型自定义 Java 类的 Generation 的属性” 所述。

表 38.1. 为 XML 架构类型自定义 Java 类的 Generation 的属性
属性必填描述

name

指定 XML Schema 原语类型映射到的 Java 类的名称。它必须是有效的 Java 类名称或 Java 原语类型的名称。您必须确保此类存在,并可以被应用程序访问。代码生成器不会检查此类。

xmlType

指定正在自定义的 XML 架构原语类型。只有在将 javaType 元素用作 globalBindings 元素的子时,才会使用此属性。

parseMethod

指定负责将数据解析到 Java 类实例中基于字符串的方法。如需更多信息,请参阅 “指定转换器”一节

printMethod

指定负责将 Java 对象转换为基于字符串的 XML 表示数据的方法。如需更多信息,请参阅 “指定转换器”一节

javaType 自定义元素可通过三种方式使用:

  • 要修改 XML Schema 原语类型的所有实例 - javaType 元素在用作 globalBindings 自定义元素的子时修改 schema 文档中的 XML Schema 类型的所有实例。以这种方式使用时,您必须为 xmlType 属性指定一个值,用于标识正在修改的 XML Schema 原语类型。

    例 38.7 “全局原语类型自定义” 显示一个 in-line 全局自定义,它指示代码生成器对架构中的所有 xsd:short 的所有实例使用 java.lang.Integer

    例 38.7. 全局原语类型自定义

    <schema targetNamespace="http://widget.com/types/widgetTypes"
            xmlns="http://www.w3.org/2001/XMLSchema"
            xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
            xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
            jaxb:version="2.0">
      <annotation>
        <appinfo>
          <jaxb:globalBindings ...>
            <jaxb:javaType name="java.lang.Integer"
                           xmlType="xsd:short" />
          </globalBindings
        </appinfo>
      </annotation>
      ...
    </schema>
  • 要修改简单的类型定义 - javaType 元素修改在应用到名为 simple 类型定义时为 XML 简单类型的所有实例生成的类。当使用 javaType 元素修改简单类型定义时,请不要使用 xmlType 属性。

    例 38.8 “用于自定义简单类型的绑定文件” 显示一个外部绑定文件,它修改名为 zipCode 的简单类型生成。

    例 38.8. 用于自定义简单类型的绑定文件

    <jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
                   xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                   jaxb:version="2.0">
      <jaxb:bindings wsdlLocation="widgets.wsdl">
        <jaxb:bindings node="xsd:simpleType[@name='zipCode']">
            <jaxb:javaType name="com.widgetVendor.widgetTypes.zipCodeType"
                           parseMethod="com.widgetVendor.widgetTypes.support.parseZipCode"
                           printMethod="com.widgetVendor.widgetTypes.support.printZipCode" />
        </jaxb:bindings>
      </jaxb:bindings>
    <jaxb:bindings>
  • 要修改复杂类型定义的元素或属性 - javaType 可以应用于复杂类型定义的单个部分,方法是将它作为 JAXB 属性自定义的一部分包含在内。javaType 元素作为子项放在属性的 baseType 元素中。当使用 javaType 元素修改复杂类型定义的特定部分时,请不要使用 xmlType 属性。

    例 38.9 “用于在 Complex Type 中自定义元素的绑定文件” 显示修改复杂类型的元素的绑定文件。

    例 38.9. 用于在 Complex Type 中自定义元素的绑定文件

    <jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
                   xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                   jaxb:version="2.0">
      <jaxb:bindings schemaLocation="enumMap.xsd">
        <jaxb:bindings node="xsd:ComplexType[@name='widgetOrderInfo']">
          <jaxb:bindings node="xsd:element[@name='cost']">
            <jaxb:property>
              <jaxb:baseType>
                <jaxb:javaType name="com.widgetVendor.widgetTypes.costType"
                                parseMethod="parseCost"
                                printMethod="printCost" >
              </jaxb:baseType>
            </jaxb:property>
          </jaxb:bindings>
        </jaxb:bindings>
      </jaxb:bindings>
    <jaxb:bindings>

    有关使用 baseType 元素的更多信息,请参阅 第 38.6 节 “指定元素或属性的基本类型”

指定转换器

Apache CXF 无法将 XML 架构原语类型转换为随机 Java 类。当您使用 javaType 元素自定义 XML Schema 原语类型的映射时,代码生成器会创建一个适配器类,用于 marshal 和 unmarshal 自定义 XML 架构原语类型。例 38.10 “JAXB Adapter 类” 中显示示例适配器类。

例 38.10. JAXB Adapter 类

public class Adapter1 extends XmlAdapter<String, javaType>
{
  public javaType unmarshal(String value)
  {
    return(parseMethod(value));
  }

  public String marshal(javaType value)
  {
    return(printMethod(value));
  }
}

parseMethodprintMethod 被对应的 parseMethod 属性和 printMethod 属性的值替代。值必须识别有效的 Java 方法。您可以通过以下两种方式之一指定方法的名称:

  • 完全限定的 Java 方法名称,格式为 packagename.ClassName.methodName
  • methodName格式的简单方法名称

    当您只提供简单方法名称时,代码生成器假定方法存在于由 javaType 元素的 name 属性指定的类中。

重要

代码生成器 不会生成 解析或打印方法。您负责提供它们。有关开发解析和打印方法的详情,请参考 “实施转换器”一节

如果没有提供 parseMethod 属性的值,则代码生成器假定 name 属性指定的 Java 类具有构造器,其第一个参数是一个 Java String 对象。生成的适配器的 unmarshal () 方法使用假定的构造器使用 XML 数据填充 Java 对象。

如果没有提供 printMethod 属性的值,则代码生成器假定 name 属性指定的 Java 类具有 toString () 方法。生成的适配器的 marshal () 方法使用假定的 toString () 方法将 Java 对象转换为 XML 数据。

如果 javaType 元素的 name 属性指定 Java 原语类型,或者 Java 原语的打包程序类型之一,则代码生成器使用默认的转换器。有关默认转换器的详情请参考 “默认原语类型转换器”一节

生成内容

“指定转换器”一节 所述,使用 javaType customization 元素为每个自定义 XML 架构原语类型触发一个适配器类的生成。适配器按顺序使用 pattern AdapterN 命名。如果您指定了两个原语类型自定义,则代码生成器会创建两个适配器类: Adapter1Adapter2

为 XML 模式构建生成的代码取决于效果的 XML 架构结构是全局定义的元素,或者被定义为复杂类型的一部分。

当 XML Schema 结构是全局定义的元素时,为类型生成的对象工厂方法将从默认方法修改,如下所示:

  • 该方法使用 @XmlJavaTypeAdapter 注释进行解码。

    该注解指示在处理此元素实例时要使用的适配器类的运行时。适配器类指定为 class 对象。

  • 默认 type 被 javaType 元素的 name 属性指定的类替代。

例 38.11 “全局元素的自定义对象工厂方法” 显示受 例 38.7 “全局原语类型自定义” 中显示的自定义影响的元素的对象工厂方法。

例 38.11. 全局元素的自定义对象工厂方法

 @XmlElementDecl(namespace = "http://widgetVendor.com/types/widgetTypes", name = "shorty")
 @XmlJavaTypeAdapter(org.w3._2001.xmlschema.Adapter1.class)
 public JAXBElement<Integer> createShorty(Integer value) {
     return new JAXBElement<Integer>(_Shorty_QNAME, Integer.class, null, value);
 }

当将 XML Schema 结构定义为复杂类型的一部分时,生成的 Java 属性将修改,如下所示:

  • 属性使用 @XmlJavaTypeAdapter 注释进行解码。

    该注解指示在处理此元素实例时要使用的适配器类的运行时。适配器类指定为 class 对象。

  • 属性的 @XmlElement 包含 type 属性。

    type 属性的值是代表生成对象的默认基本类型的类对象。对于 XML 架构原语类型,则类是 String

  • 属性使用 @XmlSchemaType 注释进行解码。

    该注解标识了结构的 XML 架构原语类型。

  • 默认 type 被 javaType 元素的 name 属性指定的类替代。

例 38.12 “自定义复杂类型” 显示受 例 38.7 “全局原语类型自定义” 中显示的自定义影响的元素的对象工厂方法。

例 38.12. 自定义复杂类型

public class NumInventory {

    @XmlElement(required = true, type = String.class) @XmlJavaTypeAdapter(Adapter1.class) @XmlSchemaType(name = "short") protected Integer numLeft;
    @XmlElement(required = true)
    protected String size;

    public Integer getNumLeft() {
        return numLeft;
    }

    public void setNumLeft(Integer value) {
        this.numLeft = value;
    }

    public String getSize() {
        return size;
    }

    public void setSize(String value) {
        this.size = value;
    }

}

实施转换器

Apache CXF 运行时不知道如何将 XML 原语类型转换为 javaType 元素指定的 Java 类,但它应调用 parseMethod 属性和 printMethod 属性指定的方法。您负责提供方法运行时调用的实现。实施的方法必须能够使用 XML 原语类型的字典结构。

为简化数据转换方法的实现,Apache CXF 提供 javax.xml.bind.DatatypeConverter 类。此类提供解析和打印所有 XML 架构原语类型的方法。parse 方法使用 XML 数据的字符串表示,它们会返回 表 34.1 “XML Schema 原语类型到 Java 原生类型映射” 中定义的默认类型实例。打印方法采用默认类型的实例,它们返回 XML 数据的字符串表示。

DatatypeConverter 类的 Java 文档可在 https://docs.oracle.com/javase/8/docs/api/javax/xml/bind/DatatypeConverter.html 中找到。

默认原语类型转换器

javaType 元素的 name 属性中指定 Java 原语类型或 Java 原语类型 Wrapper 类时,不需要为 parseMethod 属性或 printMethod 属性指定值。如果没有提供任何值,Apache CXF 运行时会替换默认的转换器。

默认数据转换器使用 JAXB DatatypeConverter 类来解析 XML 数据。默认转换器还会提供进行转换所需的任何类型广播。

Red Hat logoGithubRedditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

通过我们的产品和服务,以及可以信赖的内容,帮助红帽用户创新并实现他们的目标。

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

© 2024 Red Hat, Inc.