Java 中文官方教程 2022 版(四十九)(3)

简介: Java 中文官方教程 2022 版(四十九)

Java 中文官方教程 2022 版(四十九)(2)https://developer.aliyun.com/article/1488530

javaType 绑定声明

声明提供了一种自定义将 XML 数据类型转换为 Java 数据类型的方法。XML 提供的数据类型比 Java 更多,因此当默认的 JAXB 绑定无法充分表示您的模式时, 声明使您能够指定自定义数据类型绑定。

目标 Java 数据类型可以是 Java 内置数据类型或特定于应用程序的 Java 数据类型。如果将特定于应用程序的 Java 数据类型用作目标,则您的实现还必须为解组和组合数据提供解析和打印方法。为此,JAXB 规范支持 parseMethodprintMethod

  • 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 允许指定命名空间上下文作为打印或解析方法的第二个参数;可以是 truefalse10。默认情况下,此属性为 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>

请注意,在此示例中,globalBindingsschemaBindings声明用于分别指定全局范围和模式范围的定制。这些定制范围在范围、继承和优先级中有更详细的描述。

内联定制示例

Customize Inline 示例演示了通过内联注释对名为po.xsd的 XML 模式进行的一些基本定制。此外,该示例实现了一个自定义数据类型转换器类MyDatatypeConverter.java,展示了处理自定义数据类型转换的定制中的打印和解析方法。

总结这个示例:

  1. po.xsd是一个包含内联绑定定制的 XML 模式。
  2. MyDatatypeConverter.java 是一个 Java 类文件,实现了 po.xsd 自定义中指定的打印和解析方法。
  3. 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 编译器时,将生成元素接口CommentElementPurchaseOrderElement。相比之下,没有此自定义, 默认绑定会生成CommentPurchaseOrder。如果模式在不同的符号空间中使用相同的名称,例如在全局元素和类型定义中,此自定义可帮助您解决冲突,而不必使用单独的绑定声明逐个解决每个冲突。
  • 指定了primer.myPo包的自定义 Javadoc 工具注释。请注意,与在类级别显示的声明不同,当在包级别进行声明时,必须包含开头和结尾的标签。

类绑定声明

以下代码显示了po.xsd中的类绑定声明:

<xsd:complexType name="PurchaseOrderType">
    <xsd:annotation>
        <xsd:appinfo>
            <jxb:class name="POType">
                <jxb:javadoc>
                    A &lt;b>Purchase Order&lt;/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自定义,它导致生成两个额外的属性方法,isSetQuantityunsetQuantity。这些方法使客户端应用程序能够区分模式默认值和在实例文档中明确出现的值。

例如,在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接口中生成了unsetQuantityisSetQuantity方法。

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 属性,包括 getZipsetZip 方法。

DataType Converter 示例

DataType Converter 示例类似于 Customize Inline 示例。与 Customize Inline 示例一样,DataType Converter 示例中的定制是通过在应用程序的 XML 模式 po.xsd 中使用内联绑定声明来实现的。

Customize Inline 和 DataType Converter 示例的全局、模式和包以及大多数类自定义是相同的。DataType Converter 示例与 Customize Inline 示例不同之处在于用于将 XML 数据转换为 Java int 数据类型的 parseMethodprintMethod

具体而言,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

相关文章
|
3天前
|
机器学习/深度学习 移动开发 测试技术
《手把手教你》系列技巧篇(五十一)-java+ selenium自动化测试-字符串操作-下篇(详解教程)
【5月更文挑战第15天】自动化测试中进行断言的时候,我们可能经常遇到的场景。从一个字符串中找出一组数字或者其中的某些关键字,而不是将这一串字符串作为结果进行断言。这个时候就需要我们对字符串进行操作,宏哥这里介绍两种方法:正则和字符串切片函数split()。
18 2
|
10天前
|
Web App开发 JavaScript 前端开发
《手把手教你》系列技巧篇(三十九)-java+ selenium自动化测试-JavaScript的调用执行-上篇(详解教程)
【5月更文挑战第3天】本文介绍了如何在Web自动化测试中使用JavaScript执行器(JavascriptExecutor)来完成Selenium API无法处理的任务。首先,需要将WebDriver转换为JavascriptExecutor对象,然后通过executeScript方法执行JavaScript代码。示例用法包括设置JS代码字符串并调用executeScript。文章提供了两个实战场景:一是当时间插件限制输入时,用JS去除元素的readonly属性;二是处理需滚动才能显示的元素,利用JS滚动页面。还给出了一个滚动到底部的代码示例,并提供了详细步骤和解释。
35 10
|
10天前
|
Java 测试技术 Python
《手把手教你》系列技巧篇(三十六)-java+ selenium自动化测试-单选和多选按钮操作-番外篇(详解教程)
【4月更文挑战第28天】本文简要介绍了自动化测试的实战应用,通过一个在线问卷调查(&lt;https://www.sojump.com/m/2792226.aspx/&gt;)为例,展示了如何遍历并点击问卷中的选项。测试思路包括找到单选和多选按钮的共性以定位元素,然后使用for循环进行点击操作。代码设计方面,提供了Java+Selenium的示例代码,通过WebDriver实现自动答题。运行代码后,可以看到控制台输出和浏览器的相应动作。文章最后做了简单的小结,强调了本次实践是对之前单选多选操作的巩固。
26 0
|
1天前
|
前端开发 JavaScript 测试技术
《手把手教你》系列技巧篇(五十三)-java+ selenium自动化测试-上传文件-上篇(详细教程)
【5月更文挑战第17天】本文介绍了在Web自动化测试中处理文件上传操作的方法。Selenium的WebDriver未提供直接的API来处理文件上传,因为这涉及到操作系统级别的窗口交互,而WebDriver无法识别非Web元素。文件上传主要分为两类:基于input控件的上传和非input控件的上传。对于input控件,可以直接使用sendKeys()方法输入文件的绝对路径来模拟选择文件。在项目实战中,给出了一个简单的HTML页面和对应的Java代码示例,展示了如何使用Selenium选取并上传文件。
7 0
|
2天前
|
JavaScript 前端开发 Java
《手把手教你》系列技巧篇(五十二)-java+ selenium自动化测试-处理面包屑(详细教程)
【5月更文挑战第16天】本文介绍了网页面包屑导航的概念、作用及其实现方式。面包屑导航是一种用户界面元素,帮助用户理解他们在网站中的位置并方便返回。通常形式为“首页>分类>子分类>内容页”,最多三层结构。在自动化测试中,处理面包屑涉及获取层级关系和当前层级,可以通过查找包含面包屑的div或ul元素,再提取其中的链接来实现。文中还提供了一个基于HTML和JavaScript的简单示例,并展示了相应的自动化测试代码设计和运行结果。
10 0
|
4天前
|
搜索推荐 Java 测试技术
《手把手教你》系列技巧篇(五十)-java+ selenium自动化测试-字符串操作-上篇(详解教程)
【5月更文挑战第14天】本文介绍了自动化测试中如何从字符串中提取特定信息,主要讲解了两种方法:正则表达式和字符串切片操作。文章提供了一个测试场景,即在搜索引擎中搜索“北京宏哥”并比较百度和必应的搜索结果数量。通过字符串切片函数`split()`,可以从搜索结果的描述中提取出数字。代码示例展示了如何使用Java实现这个功能,包括在百度和必应的搜索页面获取结果数量,并进行比较。文章最后还简单提到了其他字符串截取的方法,如`substring()`和`StringUtils`类中的方法。
19 2
|
5天前
|
JavaScript 前端开发 Java
《手把手教你》系列技巧篇(四十九)-java+ selenium自动化测试-隐藏元素定位与操作(详解教程)
【5月更文挑战第13天】本文主要讨论了在Selenium自动化测试中如何处理前端隐藏元素的问题。隐藏元素通常是通过`type="hidden"`或`style="display: none;"`属性实现的,它们在页面上不可见,但仍然存在于HTML代码中。Selenium可以定位到这些隐藏元素,但无法直接进行点击、输入等操作,会报错“ElementNotInteractableException”。
28 3
|
6天前
|
JavaScript 前端开发 测试技术
《手把手教你》系列技巧篇(四十八)-java+ selenium自动化测试-判断元素是否可操作(详解教程)
【5月更文挑战第12天】本文介绍了WebDriver中用于判断元素状态的三个方法:`isEnabled()`、`isSelected()`和`isDisplayed()`。`isSelected()`检查元素是否被选中,通常用于勾选框。`isDisplayed()`则用来判断元素是否在页面上可见。`isEnabled()`方法确定元素是否可操作,例如是否能点击或输入内容。
17 1
|
7天前
|
存储 JavaScript Java
《手把手教你》系列技巧篇(四十七)-java+ selenium自动化测试-判断元素是否显示(详解教程)
【5月更文挑战第11天】WebDriver 的 `isDisplayed()` 方法用于检查页面元素是否可见,如果元素存在于DOM中且可视,返回`true`,否则返回`false`。在自动化测试中,这个方法常用于验证元素是否真正显示在页面上。示例代码展示了如何使用 `isDisplayed()` 判断百度登录页面的特定错误提示文字是否出现。
18 1
|
8天前
|
JavaScript Java 测试技术
《手把手教你》系列技巧篇(四十六)-java+ selenium自动化测试-web页面定位toast-下篇(详解教程)
【5月更文挑战第10天】本文介绍了使用Java和Selenium进行Web自动化测试的实践,以安居客网站为例。最后,提到了在浏览器开发者工具中调试和观察页面元素的方法。
22 2