Java-中文官方教程-2022-版-六-

龙哥盟 / 2025-02-21 / 原文

Java 中文官方教程 2022 版(六)

原文:docs.oracle.com/javase/tutorial/reallybigindex.html

操作相对独立名称(RDN)

原文:docs.oracle.com/javase/tutorial/jndi/newstuff/rdn.html

javax.naming.ldap.Rdn表示根据RFC 2253指定的相对独立名称(RDN)。RDN 表示 DN 的组件,如操作 LdapName 课程中所解释的那样。RDN 由类型和值对组成。RDN 的示例包括:

  • OU=Sun

  • OU=Sales+CN=J.Smith

    上面的示例显示了多值 RDN 的表示。

Rdn类提供了访问 RDN 的名称/值对、获取其字符串表示、检索Attributes视图、比较和确定 RDN 的相等性以及转义和取消转义 RDN 值部分的方法。

Rdn类是不可变的。

构造 Rdn

如果是单个名称/值对的 RDN,可以使用指定的名称和值对构造 Rdn。对于多值 RDN,应创建包含所有名称/值对的属性集,并使用以Attributes为参数的构造函数。还可以根据RFC 2253中指定的字符串表示创建 Rdn。最后,可以使用其复制构造函数克隆 Rdn。这里是一个使用不同类型构造函数创建 RDN 的示例

        Rdn rdn1 = new Rdn("ou= Juicy\\, Fruit");
        System.out.println("rdn1:" + rdn1.toString());

        Rdn rdn2 = new Rdn(rdn1);
        System.out.println("rdn2:" + rdn2.toString());

        Attributes attrs = new BasicAttributes();
        attrs.put("ou", "Juicy, Fruit");
        attrs.put("cn", "Mango");
        Rdn rdn3 = new Rdn(attrs);
        System.out.println("rdn3:" + rdn3.toString());

        Rdn rdn4 = new Rdn("ou", "Juicy, Fruit");
        System.out.println("rdn4:" + rdn4.toString());

访问 RDN 的类型/值对

可以使用以下方法获取 RDN 的类型/值:

getType()

getValue()

toAttributes()

对于由单个类型/值对组成的 RDN,getType()方法返回类型,getValue()方法返回 RDN 的值。方法toAttributes()返回类型/值对的属性视图。下面的示例打印了 RDN 的类型/值对。

        Attributes attrs = new BasicAttributes();
        attrs.put("o", "Yellow");
        attrs.put("cn", "Mango");

        // create a binary value for the RDN
        byte[] mangoJuice = new byte[6];
        for (int i = 0; i < mangoJuice.length; i++) {
            mangoJuice[i] = (byte) i;
        }
        attrs.put("ou", mangoJuice);
        Rdn rdn = new Rdn(attrs);

        System.out.println();
        System.out.println("size:" + rdn.size());
        System.out.println("getType(): " + rdn.getType());
        System.out.println("getValue(): " + rdn.getValue());

        // test toAttributes
        System.out.println();
        System.out.println("toAttributes(): " + rdn.toAttributes());

获取字符串表示

为了按照RFC 2253中指定的语法格式化 RDN 的字符串表示,可以使用:

toString()

当您使用接受String参数的 Rdn 构造函数时,您提供了 RDN 的字符串表示,并获得了一个 Rdn 实例。要做相反的操作,即获取 Rdn 实例的字符串表示,您可以使用 toString()。toString()的结果可以馈送回 Rdn 构造函数,以产生与原始 Rdn 实例相等的 Rdn 实例。

这里有一个示例

Rdn rdn = new Rdn("cn=Juicy\\,Fruit");
String str = rdn.toString();
System.out.println(str);
Rdn rdn2 = new Rdn(str);
System.out.println(rdn.equals(rdn2));    // true

比较 RDNs

下面的方法使 RDN 的比较成为可能:

equals(Object Rdn)

compareTo(Object Rdn)

您可以使用 compareTo()对 Rdn 实例列表进行排序。equals()让您确定两个 Rdns 在语法上是否相等。如果两个 Rdns 都具有相同(大小写匹配)的类型/值对,则它们是相等的。多值 RDN 中组件的顺序不重要。

这里有一个示例

        Rdn one = new Rdn("ou=Sales+cn=Bob");
        Rdn two = new Rdn("cn=Bob+ou=Sales");
        Rdn three = new Rdn("ou=Sales+cn=Bob+c=US");
        Rdn four = new Rdn("cn=lowercase");
        Rdn five = new Rdn("cn=LowerCASE");
        System.out.println(one.equals(two));    // true
        System.out.println(two.equals(three));  // false
        System.out.println(one.equals(three));  // false
        System.out.println(four.equals(five));  // true

转义和反转义特殊字符

Rdn 类的最佳用途之一是处理包含特殊字符的 DN。它会自动处理特殊字符的转义和反转义。像 ''(反斜杠)、','(逗号)、+(加号)等字符在RFC 2253中有特定的语义。您可以在 RFC2253 中找到所有特殊字符的列表。当这些字符作为 DN 中的文字时,必须用 ''(反斜杠)进行转义。

例如,考虑一个 RDN:cn=Juicy, Fruit,出现在 Juicy 和 Fruit 之间的逗号,是一个需要用 ''(反斜杠)转义的特殊字符。经过语法格式化后的 RDN 如下所示:cn=Juicy\, Fruit 然而, ''(反斜杠)字符本身是 Java 语言字符串语法中的一个特殊字符,需要再次用 ''(反斜杠)转义。Java 语言字符串格式和RFC 2253都使用 ''(反斜杠)来转义特殊字符。因此,Java 格式化的 RDN 字符串如下所示:cn=Juicy\\, Fruit 请注意,上述提到的格式化规则仅适用于 Rdn 的值组件。Rdn类提供了两个static方法来处理 RDN 值的自动转义和反转义:

escapeValue()

unescapeValue()

下面的示例显示了如何获取 DN 的字符串表示,而无需处理RFC 2253中定义的处理特殊字符的语法。

    // DN with ',' (comma)
    String unformatted = "Juicy, Fruit";
    String formatted = Rdn.escapeValue(unformatted);
    LdapName dn = new LdapName("cn=" + formatted);
    System.out.println("dn:" + dn);

    unformatted = "true+false";
    formatted = Rdn.escapeValue(unformatted); 
    dn = new LdapName("cn=" + formatted);
    System.out.println("dn:" + dn);

    // DN with a binary value as one of its attribute values
    byte[] bytes = new byte[] {1, 2, 3, 4};
    formatted = Rdn.escapeValue(bytes);
    System.out.println("Orig val: " + bytes + "Escaped val: " + formatted);

同样地,使用静态的unescapeValue()方法,可以从格式化值中获取原始字符串。这里是一个检索原始值的示例。

    // DN with ',' (comma)
    String unformatted = "Juicy, Fruit";
    String formatted = Rdn.escapeValue(unformatted);
    System.out.println("Formatted:" + formatted);
    Object original = Rdn.unescapeValue(formatted);
    System.out.println("Original:" +  original);  

    // DN with a '+' (plus)
    unformatted = "true+false";
    formatted = Rdn.escapeValue(unformatted); 
    System.out.println("Formatted:" + formatted);
    original = Rdn.unescapeValue(formatted);
    System.out.println("Original:" +  original);  

    // DN with a binary value as one of its attribute values
    byte[] bytes = new byte[] {1, 2, 3, 4};
    formatted = Rdn.escapeValue(bytes);
    System.out.println("Formatted:" + formatted);
    original = Rdn.unescapeValue(formatted);
    System.out.println("Original:" +  original);  

设置 LDAP 操作的超时时间

原文:docs.oracle.com/javase/tutorial/jndi/newstuff/readtimeout.html

当客户端向服务器发出 LDAP 请求并且服务器由于某种原因未响应时,客户端将永远等待服务器响应,直到 TCP 超时。在客户端端,用户体验实际上是一个进程挂起。为了及时控制 LDAP 请求,自 Java SE 6 以来可以为 JNDI/LDAP 服务提供程序配置读取超时。

新的环境属性:

com.sun.jndi.ldap.read.timeout

可用于指定 LDAP 操作的读取超时时间。该属性的值是表示 LDAP 操作的读取超时时间(以毫秒为单位)的整数的字符串表示。如果 LDAP 提供程序在指定的时间内未收到 LDAP 响应,则会中止读取尝试。整数应大于零。小于或等于零的整数表示未指定读取超时,相当于无限等待响应直到接收到响应,这是默认行为。

如果未指定此属性,默认情况下将等待响应直到接收到响应。

例如,env.put("com.sun.jndi.ldap.read.timeout", "5000"); 会导致 LDAP 服务提供程序在服务器在 5 秒内未响应时中止读取尝试。

这里有一个示例,ReadTimeoutTest,使用一个不响应 LDAP 请求的虚拟服务器,展示了当将此属性设置为非零值时的行为。

env.put(Context.INITIAL_CONTEXT_FACTORY,
        "com.sun.jndi.ldap.LdapCtxFactory");
env.put("com.sun.jndi.ldap.read.timeout", "1000");
env.put(Context.PROVIDER_URL, "ldap://localhost:2001");

Server s = new Server();

try {

    // start the server
    s.start();

   // Create initial context
   DirContext ctx = new InitialDirContext(env);
   System.out.println("LDAP Client: Connected to the Server");
        :
        :
} catch (NamingException e) {
   e.printStackTrace();
}

由于服务器甚至未响应 LDAP 绑定请求,当创建 InitialDirContext 时,上述程序打印下面的堆栈跟踪。客户端在等待服务器响应时超时。

Server: Connection accepted
javax.naming.NamingException: LDAP response read timed out, timeout used:1000ms.
:
:

at javax.naming.directory.InitialDirContext.<init>(InitialDirContext.java:82)
at ReadTimeoutTest.main(ReadTimeoutTest.java:32)

请注意,此属性与另一个环境属性 com.sun.jndi.ldap.connect.timeout 不同,后者设置连接到服务器的超时时间。读取超时适用于与服务器建立初始连接后从服务器接收的 LDAP 响应。

Trail: Sockets Direct Protocol

原文:docs.oracle.com/javase/tutorial/sdp/index.html

Sockets Direct Protocol(SDP)提供了对高性能网络连接的访问,例如 InfiniBand 提供的连接。本教程展示了如何启用 SDP,涉及哪些 Java API,并解释了它的工作原理。

课程:理解套接字直接协议

原文:docs.oracle.com/javase/tutorial/sdp/sockets/index.html

对于高性能计算环境,快速高效地在网络中传输数据是必需的。这样的网络通常被描述为需要高吞吐量和低延迟。高吞吐量指的是在长时间内可以提供大量处理能力的环境。低延迟指的是处理输入并提供输出之间的最小延迟,就像您在实时应用程序中所期望的那样。

在这些环境中,使用套接字流进行传输数据可能会导致瓶颈。InfiniBand(IB)由InfiniBand 贸易协会于 1999 年推出,旨在满足高性能计算的需求。IB 的最重要特性之一是远程直接内存访问(RDMA)。RDMA 使得可以直接从一台计算机的内存移动数据到另一台计算机,绕过两台计算机的操作系统,从而实现显著的性能提升。

套接字直接协议(SDP)是一种网络协议,旨在支持在 InfiniBand 结构上的流连接。SDP 支持是在 Java 平台标准版("Java SE 平台")的 JDK 7 版本中引入的,用于在 Solaris 操作系统("Solaris OS")和 Linux 操作系统上部署的应用程序。Solaris OS 自 Solaris 10 5/08 版本以来一直支持 SDP 和 InfiniBand。在 Linux 上,InfiniBand 软件包称为 OFED(OpenFabrics 企业发行版)。JDK 7 版本支持 OFED 的 1.4.2 和 1.5 版本。

概述

原文:docs.oracle.com/javase/tutorial/sdp/sockets/overview.html

SDP 支持本质上是一种 TCP 绕过技术。

当启用 SDP 并且应用程序尝试打开 TCP 连接时,TCP 机制将被绕过,通信直接传输到 IB 网络。例如,当您的应用程序尝试绑定到 TCP 地址时,基础软件将根据配置文件中的信息决定是否应重新绑定到 SDP 协议。此过程可以在绑定过程或连接过程中发生(但每个套接字仅发生一次)。

在您的代码中利用 SDP 协议无需进行 API 更改:实现是透明的,并受经典网络(java.net)和新 I/O(java.nio.channels)包的支持。查看支持的 Java API 部分,了解支持 SDP 协议的类列表。

SDP 支持默认情况下是禁用的。启用 SDP 支持的步骤如下:

  • 创建一个 SDP 配置文件。

  • 设置指定配置文件位置的系统属性。

创建一个 SDP 配置文件

原文:docs.oracle.com/javase/tutorial/sdp/sockets/file.html

一个 SDP 配置文件是一个文本文件,您可以决定这个文件将存放在文件系统的哪个位置。配置文件中的每一行都是一个注释或一个规则。注释以井号字符(#)开头,井号字符后的所有内容将被忽略。

有两种类型的规则,如下:

  • "bind"规则表示当 TCP 套接字绑定到与规则匹配的地址和端口时,应使用 SDP 协议传输。

  • "connect"规则表示当未绑定的 TCP 套接字尝试连接到与规则匹配的地址和端口时,应使用 SDP 协议传输。

一个规则的形式如下:

("bind"|"connect")1*LWSP-char(hostname|ipaddress)["/"prefix])1*LWSP-char("*"|port)["-"("*"|port)]


解码符号:

1LWSP-char表示任意数量的线性空白字符(制表符或空格)可以分隔标记。方括号表示可选文本。符号(xxx* | yyy)表示标记将包括xxxyyy中的一个,但不会同时包括两者。引号中的字符表示文字。


第一个关键字指示规则是bind还是connect规则。下一个标记指定主机名或文字 IP 地址。当指定文字 IP 地址时,您还可以指定前缀,表示 IP 地址范围。第三个也是最后一个标记是端口号或端口号范围。

在这个示例配置文件中考虑以下符号:

# Use SDP when binding to 192.0.2.1
bind 192.0.2.1 *

# Use SDP when connecting to all application services on 192.0.2.*
connect 192.0.2.0/24     1024-*

# Use SDP when connecting to the http server or a database on examplecluster
connect examplecluster.example.com   80
connect examplecluster.example.com   3306

示例文件中的第一条规则指定 SDP 用于本地 IP 地址192.0.2.1上的任何端口()。对于每个分配给 InfiniBand 适配器的本地地址,您将添加一个绑定规则。(InfiniBand 适配器*相当于 InfiniBand 的网络接口卡(NIC)。)如果您有多个 IB 适配器,您将为分配给这些适配器的每个地址使用一个绑定规则。

示例文件中的第二条规则指定每当连接到192.0.2.*并且目标端口大于或等于 1024 时,将使用 SDP。IP 地址前缀/24表示 32 位 IP 地址的前 24 位应与指定地址匹配。IP 地址的每个部分使用 8 位,因此 24 位表示 IP 地址应匹配192.0.2,最后一个字节可以是任何值。端口标记上的-*符号指定“及以上”。端口范围,例如 1024—2056,也是有效的,并且将包括指定范围的端点。

示例文件中的最后规则指定一个主机名(examplecluster),首先分配给 http 服务器的端口(80),然后分配给数据库的端口(3306)。与文字 IP 地址不同,主机名可以转换为多个地址。当指定主机名时,它匹配主机名在名称服务中注册的所有地址。

启用 SDP 协议

原文:docs.oracle.com/javase/tutorial/sdp/sockets/enable.html

SDP 支持默认情况下是禁用的。要启用 SDP 支持,请设置com.sun.sdp.conf系统属性,提供配置文件的位置。以下示例启动一个使用名为sdp.conf的配置文件的应用程序:

% java -Dcom.sun.sdp.conf=sdp.conf -Djava.net.preferIPv4Stack=true  *ExampleApplication*

ExampleApplication指的是试图连接到 IB 适配器的客户端应用程序。

请注意,此示例指定另一个系统属性java.net.preferIPv4Stack。有关为什么使用此属性的更多信息,请参见 Issues 部分。

调试 SDP

原文:docs.oracle.com/javase/tutorial/sdp/sockets/debug.html

你可以通过使用-Dcom.sun.sdp.debug标志来启用调试消息。如果你指定一个文件,消息将被输出到该文件。否则,消息将被打印到标准输出。

这个第一个示例展示了打印到标准输出的示例消息:

% java -Dcom.sun.sdp.conf=sdp.conf -Dcom.sun.sdp.debug *ExampleApplicaton*
BIND to 192.0.2.1:5000 (socket converted to SDP protocol)
CONNECT to 129.156.232.160:80 (no match)
CONNECT to 192.0.2.2:80 (socket converted to SDP protocol)

这个第二个示例展示了输出重定向到名为debug.log的文件:

% java -Dcom.sun.sdp.conf=sdp.conf -Dcom.sun.sdp.debug=debug.log *ExampleApplication* 
[1] 27310
% tail -f debug.log
BIND to 192.0.2.1:5000 (socket converted to SDP protocol)

SDP 的技术问题

原文:docs.oracle.com/javase/tutorial/sdp/sockets/issues.html

  • IPv4 和 IPv6 不兼容

    互联网协议第 4 版(IPv4)长期以来一直是 Internet 协议(IP)的行业标准版本,用于在 Internet 上传输数据。互联网协议第 6 版(IPv6)是下一代 Internet 层协议。今天仍在使用这两个版本的 IP。

    IPv4 地址是 32 位长,以十进制格式编写,并用句点分隔。IPv6 地址是 128 位长,以十六进制格式编写,并用冒号分隔。IPv4 地址不能直接在 IPv6 中使用,但 IPv6 支持一种特殊类别的地址:IPv4 映射地址。在 IPv4 映射地址中,前 80 位设置为零,接下来的 16 位设置为 1,最后 32 位表示 IPv4 地址。

    例如,这里是相同的 IP 地址以两种格式表示:

    IPv4 address                  IPv4-mapped address (for use in IPv6)
    192.0.2.1                   ::ffff:192.0.2.1
    
    

    默认情况下,如果 IB 适配器中启用了 IPv6,则 Java 平台将使用 IPv6。然而,在 Solaris 操作系统或 Linux 下目前不支持 IPv4 映射地址。因此,如果您想在 JDK 7 下使用 IPv4 地址格式,必须指定java.net.preferIPv4Stack属性,如下例所示:

    % java -Dcom.sun.sdp.conf=sdp.conf -Djava.net.preferIPv4Stack=true  *MyApplication*
    
    
  • 错误

    在早期 InfiniBand 实现中发现了一些错误。这些错误在 Solaris 10 10/09 版本中已修复。请确保您至少使用此版本。

Solaris 和 Linux 支持

原文:docs.oracle.com/javase/tutorial/sdp/sockets/support.html

Solaris 10

要测试 SDP 是否已启用,请使用sdpadm(1M)命令:

% /usr/sbin/sdpadm status
SDP is Enabled

你可以使用 grep 命令在/etc/path_to_inst文件中搜索字符串"ibd",以查看网络上支持的 IB 适配器列表。

其他你可能会发现有用的命令包括ib(7D)、ibd(7D)和sdp(7D)。

Solaris 11

你可以使用以下命令获取 InfiniBand 分区链接信息:

% dladm show-port -o LINK

其他你可能会发现有用的命令包括ib(7D)、ibd(7D)和sdp(7D)。

Linux

你可以使用以下命令获取 InfiniBand 适配器的列表:

% egrep "^[ \t]+ib" /proc/net/dev

支持的 Java API

原文:docs.oracle.com/javase/tutorial/sdp/sockets/supported.html

所有使用 TCP 的 API 都可以使用 SDP,特别包括以下类:

  • java.net

    • Socket

    • ServerSocket

  • java.nio.channels 包:

    • SocketChannel

    • ServerSocketChannel

    • AsynchronousSocketChannel

    • AsynchronousServerSocketChannel

当启用 SDP 支持时,它会在不需要对您的代码进行任何更改的情况下正常工作。不需要编译。然而,重要的是要知道套接字只绑定一次。连接是隐式绑定。因此,如果套接字之前没有绑定并且调用了 connect,则绑定将在那个时候发生。

例如,考虑以下代码片段:

AsynchronousSocketChannel ch = AsynchronousSocketChannel.open();
ch.bind(local);
Future<Void> result = ch.connect(remote);

在此代码片段中,当在套接字上调用 bind 时,异步套接字通道将绑定到本地 TCP 地址。然后,代码尝试使用相同的套接字连接到远程地址。如果远程地址使用配置文件中指定的 InfiniBand,则连接不会转换为 SDP,因为套接字先前已绑定。

更多信息请参考

原文:docs.oracle.com/javase/tutorial/sdp/sockets/info.html

  • Alan Bateman 的博客:套接字直接协议

  • Nitin Hande 的博客:在 OpenSolaris 上使用 IPoIB

  • Anish Gupta 的博客关于InfiniBand 支持

教程:Java Architecture for XML Binding

原文:docs.oracle.com/javase/tutorial/jaxb/index.html

Java Architecture for XML Binding (JAXB) 教程介绍了 Java Architecture for XML Binding (JAXB) 技术,通过 JAXB 应用示例。

在阅读本教程之前

要理解并使用 Java Architecture for XML Binding (JAXB) 教程中的信息,您应该具备以下技术知识:

  • Java 编程语言及其开发环境

  • 可扩展标记语言(XML)

本教程详细讨论了仅与 JAXB 相关的代码。

简要描述了 JAXB 技术,包括其目的和主要特点。

课程:JAXB 简介

原文:docs.oracle.com/javase/tutorial/jaxb/intro/index.html

Java Architecture for XML Binding (JAXB)提供了一种快速便捷的方式来绑定 XML 模式和 Java 表示,使 Java 开发人员能够轻松地在 Java 应用程序中整合 XML 数据和处理功能。作为这个过程的一部分,JAXB 提供了将 XML 实例文档解组(读取)为 Java 内容树的方法,然后将 Java 内容树重新组合(写入)为 XML 实例文档的方法。JAXB 还提供了一种从 Java 对象生成 XML 模式的方法。

JAXB 2.0 对 JAXB 1.0 进行了几项重要改进:

  • 支持所有 W3C XML Schema 功能。(JAXB 1.0 没有为一些 W3C XML Schema 功能指定绑定。)

  • 支持将 Java 绑定到 XML,通过添加javax.xml.bind.annotation包来控制此绑定。(JAXB 1.0 规定了 XML Schema 到 Java 的映射,但没有规定 Java 到 XML Schema 的映射。)

  • 生成的基于模式的类数量显著减少。

  • 通过 JAXP 1.3 验证 API 提供的额外验证功能。

  • 更小的运行时库。

本课程描述了 JAXB 架构、功能和核心概念,并提供了使用 JAXB 的逐步示例过程。

JAXB 架构

原文:docs.oracle.com/javase/tutorial/jaxb/intro/arch.html

本节描述了 JAXB 处理模型中的组件和交互。

架构概述

以下图显示了构成 JAXB 实现的组件。

图:JAXB 架构概述

JAXB 架构概述

JAXB 实现由以下架构组件组成:

  • 模式编译器:将源模式绑定到一组基于模式的程序元素。绑定由基于 XML 的绑定语言描述。

  • 模式生成器:将一组现有程序元素映射到一个派生模式。映射由程序注解描述。

  • 绑定运行时框架:提供了用于访问、操作和验证 XML 内容的解组(读取)和组装(写入)操作,使用基于模式的或现有程序元素。

JAXB 绑定过程

以下图显示了 JAXB 绑定过程中发生的情况。

图:JAXB 绑定过程中的步骤

JAXB 绑定过程

JAXB 数据绑定过程中的一般步骤如下:

  1. 生成类:将 XML 模式用作 JAXB 绑定编译器的输入,以根据该模式生成基于 JAXB 的类。

  2. 编译类:所有生成的类、源文件和应用程序代码都必须被编译。

  3. Unmarshal:根据源模式中的约束编写的 XML 文档由 JAXB 绑定框架解组。请注意,JAXB 还支持从文件和文档以外的源解组 XML 数据,如 DOM 节点、字符串缓冲区、SAX 源等。

  4. 生成内容树:解组过程生成从生成的 JAXB 类实例化的数据对象内容树;此内容树表示源 XML 文档的结构和内容。

  5. 验证(可选):解组过程涉及在生成内容树之前验证源 XML 文档。请注意,如果您在第 6 步中修改内容树,您还可以使用 JAXB 验证操作在将内容组装回 XML 文档之前验证更改。

  6. 处理内容:客户端应用程序可以通过使用绑定编译器生成的接口修改 Java 内容树表示的 XML 数据。

  7. Marshal:处理后的内容树被组装成一个或多个 XML 输出文档。在组装之前可能会进行验证。

更多关于 Unmarshalling

Unmarshalling 提供了客户端应用程序将 XML 数据转换为基于 JAXB 的 Java 对象的能力。

更多关于 Marshalling

Marshalling 提供了客户端应用程序将基于 JAXB 的 Java 对象树转换为 XML 数据的能力。

默认情况下,Marshaller在生成 XML 数据时使用 UTF-8 编码。

在组合之前,客户端应用程序不需要验证 Java 内容树。也没有要求 Java 内容树在组合成 XML 数据时必须符合其原始模式。

更多关于验证

验证是验证 XML 文档是否符合模式中表达的所有约束的过程。JAXB 1.0 在解组时提供了验证,并且还可以在 JAXB 内容树上按需进行验证。JAXB 2.0 只允许在解组和组合时进行验证。Web 服务处理模型是在读取数据时宽松,在写出数据时严格。为了符合该模型,在组合时添加了验证,以便用户可以确认在修改 JAXB 表单中的文档时未使 XML 文档无效。

表示 XML 内容

原文:docs.oracle.com/javase/tutorial/jaxb/intro/repcon.html

本节描述了 JAXB 如何将 XML 内容表示为 Java 对象。

XML 模式的 Java 表示

JAXB 支持将生成的类分组到 Java 包中。一个包包括以下内容:

  • 从 XML 元素名称派生的 Java 类名称,或者由绑定自定义指定。

  • 一个ObjectFactory类,这是一个工厂,用于返回绑定的 Java 类的实例。

绑定 XML 模式

原文:docs.oracle.com/javase/tutorial/jaxb/intro/bind.html

本节描述了 JAXB 使用的默认 XML 到 Java 绑定。所有这些绑定都可以通过使用自定义绑定声明全局或逐案例地进行覆盖。有关默认 JAXB 绑定的完整信息,请参阅JAXB 规范。

简单类型定义

使用简单类型定义的模式组件通常绑定到 Java 属性。由于有不同类型的模式组件,以下 Java 属性属性(对于模式组件通用)包括:

  • 基本类型

  • 集合类型,如果有的话

  • 谓词

其余的 Java 属性属性在使用simple类型定义的模式组件中指定。

默认数据类型绑定

以下部分解释了默认模式到 Java、JAXBElement和 Java 到模式数据类型绑定。

模式到 Java 的映射

Java 语言提供了比 XML 模式更丰富的数据类型。以下表格提供了 JAXB 中 XML 数据类型到 Java 数据类型的映射。

表:XML 模式内置数据类型的 JAXB 映射

XML 模式类型 Java 数据类型
xsd:string java.lang.String
xsd:integer java.math.BigInteger
xsd:int int
xsd.long long
xsd:short short
xsd:decimal java.math.BigDecimal
xsd:float float
xsd:double double
xsd:boolean boolean
xsd:byte byte
xsd:QName javax.xml.namespace.QName
xsd:dateTime javax.xml.datatype.XMLGregorianCalendar
xsd:base64Binary byte[]
xsd:hexBinary byte[]
xsd:unsignedInt long
xsd:unsignedShort int
xsd:unsignedByte short
xsd:time javax.xml.datatype.XMLGregorianCalendar
xsd:date javax.xml.datatype.XMLGregorianCalendar
xsd:g javax.xml.datatype.XMLGregorianCalendar
xsd:anySimpleType java.lang.Object
xsd:anySimpleType java.lang.String
xsd:duration javax.xml.datatype.Duration
xsd:NOTATION javax.xml.namespace.QName

JAXBElement 对象

当无法通过 XML 内容的派生 Java 表示来推断 XML 元素信息时,会提供一个JAXBElement对象。该对象具有获取和设置对象名称和对象值的方法。

Java 到模式的映射

以下表格显示了 Java 类到 XML 数据类型的默认映射。

表:XML 数据类型到 Java 类的 JAXB 映射

Java 类 XML 数据类型
java.lang.String xs:string
java.math.BigInteger xs:integer
java.math.BigDecimal xs:decimal
java.util.Calendar xs:dateTime
java.util.Date xs:dateTime
javax.xml.namespace.QName xs:QName
java.net.URI xs:string
javax.xml.datatype.XMLGregorianCalendar xs:anySimpleType
javax.xml.datatype.Duration xs:duration
java.lang.Object xs:anyType
java.awt.Image xs:base64Binary
javax.activation.DataHandler xs:base64Binary
javax.xml.transform.Source xs:base64Binary
java.util.UUID xs:string

自定义生成的类和 Java 程序元素

原文:docs.oracle.com/javase/tutorial/jaxb/intro/customize.html

以下部分描述了如何自定义生成的 JAXB 类和 Java 程序元素。

模式到 Java

自定义 JAXB 绑定声明使您能够在 XML 模式中包含 Java 特定的细化,例如类和包名称映射,以定制生成的 JAXB 类。

JAXB 提供了两种自定义 XML 模式的方法:

  • 作为源 XML 模式中的内联注释

  • 作为传递给 JAXB 绑定编译器的外部绑定自定义文件中的声明

提供了显示如何自定义 JAXB 绑定的代码示例,稍后在本文档中提供。

Java 到模式

javax.xml.bind.annotation 包中定义的 JAXB 注释可用于自定义 Java 程序元素到 XML 模式的映射。以下表总结了可以与 Java 包一起使用的 JAXB 注释。

表:与 Java 包相关的 JAXB 注释

注释 描述和默认设置

| @XmlSchema | 将包映射到 XML 目标命名空间。默认设置:

@XmlSchema ( 
    xmlns = {}, 
    namespace = "", 
    elementFormDefault = XmlNsForm.UNSET, 
    attributeFormDefault = XmlNsForm.UNSET
)

|

| @XmlAccessorType | 控制字段和属性的默认序列化。默认设置:

@XmlAccessorType (
    value = AccessType.PUBLIC_MEMBER 
)

|

| @XmlAccessorOrder | 控制映射到 XML 元素的属性和字段的默认排序。默认设置:

@XmlAccessorOrder (
    value = AccessorOrder.UNDEFINED
)

|

| @XmlSchemaType | 允许自定义映射到 XML 模式内置类型。默认设置:

@XmlSchemaType (
    namespace = 
    "http://www.w3.org/2001/XMLSchema", 
    type = DEFAULT.class
)

|

@XmlSchemaTypes 用于定义多个 @XmlSchemaType 注释的容器注释。默认设置:无

以下表总结了可以与 Java 类一起使用的 JAXB 注释。

表:与 Java 类相关的 JAXB 注释

注释 描述和默认设置

| @XmlType | 将 Java 类映射到模式类型。默认设置:

@XmlType (
    name = "##default", 
    propOrder = {""}, 
    namespace = "##default", 
    factoryClass = DEFAULT.class, 
    factoryMethod = ""
)

|

| @XmlRootElement | 将全局元素与类映射到的模式类型关联。默认设置:

@XmlRootElement (
    name = "##default", 
    namespace = "##default" 
)

|

以下表总结了可以与 Java enum 类型一起使用的 JAXB 注释。

表:与 Java enum 类型相关的 JAXB 注释

注释 描述和默认设置

| @XmlEnum | 将 Java 类型映射到 XML 简单类型。默认设置:

@XmlEnum ( value = String.class )

|

@XmlEnumValue 将 Java 类型映射到 XML 简单类型。默认设置:无

| @XmlType | 将 Java 类映射到模式类型。默认设置:


@XmlType (
    name = "##default", 
    propOrder = {""}, 
    namespace = "##default", 
    factoryClass = DEFAULT.class, 
    factoryMethod = ""
)

|

| @XmlRootElement | 将全局元素与类映射到的模式类型关联。默认设置:

@XmlRootElement (
    name = "##default", 
    namespace = "##default" 
)

|

以下表总结了可以与 Java 属性和字段一起使用的 JAXB 注释。

表:与 Java 属性和字段相关的 JAXB 注释

注释 描述和默认设置

| @XmlElement | 将 JavaBeans 属性或字段映射到从属性或字段名称派生的 XML 元素。默认设置:

@XmlElement (
    name = "##default", 
    nillable = false, 
    namespace = "##default", 
    type = DEFAULT.class, 
    defaultValue = "\u0000"
)

|

@XmlElements 用于定义多个 @XmlElement 注解的容器注解。默认设置:无

| @XmlElementRef | 将 JavaBeans 属性或字段映射到从属性或字段类型派生的 XML 元素。默认设置:

@XmlElementRef (
    name = "##default", 
    namespace = "##default", 
    type = DEFAULT.class
)

|

@XmlElementRefs 用于定义多个 @XmlElementRef 注解的容器注解。默认设置:无

| @XmlElementWrapper | 在 XML 表示周围生成一个包装器元素。通常用作集合周围的包装 XML 元素。默认设置:

@XmlElementWrapper (
    name = "##default", 
    namespace = "##default", 
    nillable = false
)

|

| @XmlAnyElement | 将 JavaBeans 属性映射到 XML 信息集表示或 JAXB 元素。默认设置:

@XmlAnyElement (
    lax = false, 
    value = W3CDomHandler.class
)

|

| @XmlAttribute | 将一个 JavaBeans 属性映射到 XML 属性。默认设置:

@XmlAttribute (
    name = ##default, 
    required = false, 
    namespace = "##default" 
)

|

@XmlAnyAttribute 将 JavaBeans 属性映射到通配符属性映射。默认设置:无
@XmlTransient 防止将 JavaBeans 属性映射到 XML 表示。默认设置:无
@XmlValue 定义类到 XML Schema 复杂类型或 XML Schema 简单类型的映射。默认设置:无
@XmlID 将 JavaBeans 属性映射到 XML ID。默认设置:无
@XmlIDREF 将 JavaBeans 属性映射到 XML IDREF。默认设置:无
@XmlList 将属性映射到简单类型列表。默认设置:无
@XmlMixed 标记 JavaBeans 多值属性以支持混合内容。默认设置:无
@XmlMimeType 关联控制属性的 XML 表示的 MIME 类型。默认设置:无
@XmlAttachmentRef 标记字段/属性,其 XML 表单是指向 mime 内容的 URI 引用。默认设置:无
@XmlInlineBinaryData 禁用对绑定到 XML 中 base64 编码二进制数据的数据类型考虑 XOP 编码。默认设置:无

以下表总结了可以与对象工厂一起使用的 JAXB 注解。

表格:与对象工厂相关的 JAXB 注解

注解 描述和默认设置

| @XmlElementDecl | 将工厂方法映射到 XML 元素。默认设置:

@XmlElementDecl (
    scope = GLOBAL.class, 
    namespace = "##default", 
    substitutionHeadNamespace = "##default", 
    substitutionHeadName = ""
)

|

以下表总结了可以与适配器一起使用的 JAXB 注解。

表格:与适配器相关的 JAXB 注解

注解 描述和默认设置

| @XmlJavaTypeAdapter | 使用实现 @XmlAdapter 注解的适配器进行自定义编组。默认设置:

@XmlJavaTypeAdapter ( type = DEFAULT.class )

|

@XmlJavaTypeAdapters 用于在包级别定义多个 @XmlJavaTypeAdapter 注解的容器注解。默认设置:无

JAXB 示例

原文:docs.oracle.com/javase/tutorial/jaxb/intro/examples.html

以下部分描述如何使用包含在 JAXB RI 捆绑包中的示例应用程序。JAXB RI 捆绑包可从jaxb.java.net获取。下载并安装 JAXB RI 捆绑包。示例位于jaxb-ri-install/samples/目录中。这些示例演示并构建了关键的 JAXB 功能和概念。请按照呈现的顺序执行这些步骤。

阅读完本节后,您应该对 JAXB 感到足够自信,可以:

  • 从 XML 模式生成 JAXB Java 类

  • 在 Java 应用程序中使用基于模式的 JAXB 类解组和组合 XML 内容

  • 使用基于模式的 JAXB 类创建 Java 内容树

  • 在解组期间和运行时验证 XML 内容

  • 自定义 JAXB 模式到 Java 绑定

本文描述了三组示例:

  • 基本示例(修改 Marshal、Unmarshal Validate)演示了基本的 JAXB 概念,如使用默认设置和绑定来解组、组合和验证 XML 内容。

  • 自定义示例(Customize Inline、Datatype Converter、External Customize)演示了将 XML 模式默认绑定到 Java 对象的各种自定义方式。

  • java-to-schema 示例展示了如何使用注解将 Java 类映射到 XML 模式。


注意:基本和自定义示例基于采购订单场景。每个示例使用一个 XML 文档po.xml,根据一个 XML 模式po.xsd编写。这些文档源自由 David C. Fallside 编辑的W3C XML Schema Part 0: Primer。


基本和自定义示例目录包含几个基本文件:

  • po.xsd是作为 JAXB 绑定编译器输入的 XML 模式,将从中生成基于模式的 JAXB Java 类。对于自定义内联和数据类型转换器示例,此文件包含内联绑定自定义。

  • po.xml是包含示例 XML 内容的采购订单 XML 文件,在每个示例中解组为 Java 内容树。这个文件在每个示例中几乎相同;为了突出不同的 JAXB 概念,存在轻微的内容差异。

  • Main.java是每个示例的主要 Java 类。

  • build.xml是一个 Ant 项目文件,为您提供方便。使用 Ant 工具自动生成、编译和运行基于模式的 JAXB 类。build.xml文件在示例之间有所不同。

  • inline-customize示例中的MyDatatypeConverter.java是一个 Java 类,用于提供自定义数据类型转换。

  • External Customize 示例中的binding.xjb是一个外部绑定声明文件,传递给 JAXB 绑定编译器以自定义默认的 JAXB 绑定。

以下表简要描述了基本、定制和 Java 到模式 JAXB 示例。

表:基本 JAXB 示例

示例名称 描述
Modify Marshal 演示如何修改 Java 内容树。
Unmarshal Validate 演示如何在解组期间启用验证。

表:定制 JAXB 示例

示例名称 描述
Customize Inline 演示如何通过在 XML 模式中使用内联注解来定制默认的 JAXB 绑定。
Datatype Converter 演示了将 XML simpleType定义绑定到 Java 数据类型的替代、更简洁的绑定方法,类似于内联定制示例。
External Customize 演示如何使用外部绑定声明文件来传递对 JAXB 绑定编译器的只读模式进行绑定自定义。

表:Java 到模式 JAXB 示例

示例名称 描述
Create Marshal 演示如何使用 ObjectFactory 类创建 Java 内容树并将其编组为 XML 数据。还演示了如何向 JAXB 列表属性添加内容。
XmlAccessorOrder 演示如何在 Java 类中使用@XmlAccessorOrder@XmlType.propOrder映射注解来控制 Java 类型在编组或解组 XML 内容时的顺序。
XmlAdapter 演示如何使用接口XmlAdapter和注解@XmlJavaTypeAdapter为使用整数(int)作为键和字符串(String)作为值的HashMap(字段)提供自定义映射 XML 内容的方法。
XmlAttribute 演示如何使用注解@XmlAttribute来定义一个属性或字段作为 XML 属性处理。
XmlRootElement 演示如何使用注解@XmlRootElement为相应类的 XML 模式类型定义 XML 元素名称。
XmlSchemaType Class 演示如何使用注解@XmlSchemaType来自定义属性或字段与 XML 内置类型的映射。
XmlType 演示如何使用注解@XmlType将一个类或enum类型映射到 XML 模式类型。

JAXB 编译器选项

JAXB XJC 模式绑定编译器将源 XML 模式转换或绑定到 Java 编程语言中的一组 JAXB 内容类。编译器类xjc提供为:在 Solaris/Linux 上为xjc.sh,在 Windows 上为xjc.bat在 JAXB RI 捆绑包中。xjc类包含在 JDK 类库中(在 tools.jar 中)。

xjc.shxjc.bat都接受相同的命令行选项。您可以通过在没有任何选项或使用-help开关的情况下调用脚本来显示快速使用说明。语法如下:

xjc [-options ...] <schema file/URL/dir/jar>... [-b >bindinfo<] ...

如果指定了dir,则将编译目录中的所有模式文件。如果指定了jar,将编译/META-INF/sun-jaxb.episode 绑定文件。

xjc命令行选项如下:

-nv

不执行输入模式或模式的严格验证。默认情况下,xjc 在处理之前会对源模式进行严格验证。请注意,这并不意味着绑定编译器不会执行任何验证;它只会执行较少严格的验证。

-extension

默认情况下,XJC 绑定编译器严格执行 JAXB 规范的兼容性章节中概述的规则。在默认(严格)模式下,您也只能使用规范中定义的绑定自定义。通过使用-extension开关,您可以使用 JAXB 供应商扩展。

-b file

指定一个或多个要处理的外部绑定文件。(每个绑定文件必须有自己的-b开关。)外部绑定文件的语法是灵活的。您可以有一个包含多个模式的自定义的单个绑定文件,或者您可以将自定义拆分为多个绑定文件。此外,命令行中模式文件和绑定文件的顺序无关紧要。

-d dir

默认情况下,XJC 绑定编译器在当前目录中生成 Java 内容类。使用此选项指定替代输出目录。目录必须已经存在;XJC 绑定编译器不会为您创建一个。

-p package

指定替代输出目录。默认情况下,XJC 绑定编译器将在当前目录中生成 Java 内容类。输出目录必须已经存在;XJC 绑定编译器不会为您创建一个。

-httpproxy proxy

指定 HTTP/HTTPS 代理。格式为[``*user*``[:``*password*``]@]``*proxyHost*``[:``*proxyPort*``]。旧的-host-port选项仍受参考实现支持以保持向后兼容性,但它们已被弃用。

-httpproxyfile f

类似于-httpproxy选项,但将参数放在文件中以保护密码。

-classpath arg

指定用于<jxb:javaType><xjc:superClass>自定义的客户端应用程序类文件的位置。

-catalog file

指定目录文件以解析外部实体引用。支持 TR9401、XCatalog 和 OASIS XML Catalog 格式。有关更多信息,请参阅 XML 实体和 URI 解析器文档或检查 catalog-resolver 示例应用程序。

-readOnly

强制 XJC 绑定编译器将生成的 Java 源文件标记为只读。默认情况下,XJC 绑定编译器不会写保护生成的 Java 源文件。

-npa

抑制将包级别注释生成到**/package-info.java中。使用此开关会导致生成的代码将这些注释内部化到其他生成的类中。

-no-header

抑制生成带有时间戳的文件头。

-target (2.0|2.1)

行为类似于 XJC 2.0 或 2.1,并生成不使用任何 XJC 2.2 功能的代码。

-enableIntrospection

启用正确生成布尔值 getter/setter 以启用 Bean Introspection api。

-contentForWildcard

为具有多个 xs:any 派生元素的类型生成内容属性。

-xmlschema

将输入模式视为 W3C XML 模式(默认)。 如果不指定此开关,则将处理输入模式为 W3C XML 模式。

-verbose

在编译器输出中更加详细。

-quiet

抑制编译器输出,如进度信息和警告。

-help

显示编译器开关的简要摘要。

-version

显示编译器版本信息。

-fullversion

显示编译器的完整版本信息。

-Xinject-code

将指定的 Java 代码片段注入生成的代码中。

-Xlocator

启用生成代码的源位置支持。

-Xsync-methods

生成带有synchronized关键字的访问器方法。

-mark-generated

使用-@javax.annotation.生成的注释标记生成的代码。

-episode *FILE*

为单独编译生成剧集文件。

JAXB 模式生成器选项

JAXB 模式生成器schemagen为您的 Java 类中引用的每个命名空间创建一个模式文件。 模式生成器可以通过使用适用于您平台的bin目录中的适当schemagen shell 脚本启动。 模式生成器仅处理 Java 源文件。 如果您的 Java 源引用其他类,则这些源必须从系统的 CLASSPATH 环境变量中访问; 否则,在生成模式时将出现错误。 无法控制生成的模式文件的名称。

通过调用脚本而不使用任何选项或使用-help选项,您可以显示快速使用说明。 语法如下:

schemagen [-d *path*] 
    [*java-source-files*]

-d path 选项指定了处理器生成和javac生成的类文件的位置。

关于模式到 Java 绑定

当您针对基本示例中使用的po.xsd XML 模式运行 JAXB 绑定编译器(解组读取,修改编组,解组验证)时,JAXB 绑定编译器将生成一个名为primer.po的 Java 包,其中包含下表中描述的类。

表:基本示例中的基于模式的 JAXB 类

描述
primer/po/Items.java 公共接口,绑定到名为ItemscomplexType模式。
primer/po/ObjectFactory.java 公共类,扩展com.sun.xml.bind.DefaultJAXBContextImpl; 用于创建指定接口的实例。 例如,ObjectFactorycreateComment()方法实例化Comment对象。
primer/po/PurchaseOrderType.java 公共接口,绑定到名为PurchaseOrderTypecomplexType模式。
primer/po/USAddress.java 公共接口,绑定到名为USAddresscomplexType模式。

这些类及其与基本示例源 XML 模式的特定绑定在以下表中描述。

表:基本示例的模式到 Java 绑定

XML Schema JAXB Binding

|

<xsd:schema xmlns:xsd=
 "http://www.w3.org/2001/XMLSchema">

|

<xsd:complexType 
  name="PurchaseOrderType">
  <xsd:sequence>
    <xsd:element 
      name="shipTo" 
      type="USAddress"/>
    <xsd:element 
      name="billTo" 
      type="USAddress"/>
    <xsd:element 
      ref="comment" 
      minOccurs="0"/>
    <xsd:element 
      name="items"
      type="Items"/>
  </xsd:sequence>
  <xsd:attribute 
    name="orderDate"
    type="xsd:date"/>
</xsd:complexType>

PurchaseOrderType.java

|

<xsd:complexType 
  name="USAddress">
  <xsd:sequence>
    <xsd:element 
      name="name" 
      type="xsd:string"/>
    <xsd:element 
      name="street" 
      type="xsd:string"/>
    <xsd:element 
      name="city" 
      type="xsd:string"/>
    <xsd:element 
      name="state" 
      type="xsd:string"/>
    <xsd:element 
      name="zip" 
      type="xsd:decimal"/>
  </xsd:sequence>
  <xsd:attribute 
    name="country" 
    type="xsd:NMTOKEN" 
    fixed="US"/>
</xsd:complexType>

USAddress.java

|

<xsd:complexType 
  name="Items">
  <xsd:sequence>
    <xsd:element 
      name="item" 
      minOccurs="1" 
      maxOccurs="unbounded">

Items.java

|

<xsd:complexType>
  <xsd:sequence>
    <xsd:element 
      name="productName" 
      type="xsd:string"/>
    <xsd:element 
      name="quantity">
      <xsd:simpleType>
        <xsd:restriction 
          base="xsd:positiveInteger">
          <xsd:maxExclusive 
            value="100"/>
        </xsd:restriction>
      </xsd:simpleType>
    </xsd:element>
    <xsd:element 
      name="USPrice" 
      type="xsd:decimal"/>
    <xsd:element 
      ref="comment" 
      minOccurs="0"/>
    <xsd:element 
      name="shipDate" 
      type="xsd:date" 
      minOccurs="0"/>
  </xsd:sequence>
  <xsd:attribute 
    name="partNum" 
    type="SKU" 
    use="required"/>
</xsd:complexType>

Items.ItemType

|

</xsd:element>
</xsd:sequence>
</xsd:complexType>

|

<!-- Stock Keeping Unit, a code for 
    identifying products -->

|

<xsd:simpleType 
  name="SKU">
  <xsd:restriction 
    base="xsd:string">
    <xsd:pattern 
      value="\d{3}-[A-Z]{2}"/>
  </xsd:restriction>
</xsd:simpleType>

|

</xsd:schema>

基于模式的 JAXB 类

接下来的部分简要解释了 JAXB 绑定编译器为示例生成的以下各个单独类的功能:

  • Items

  • ObjectFactory

  • PurchaseOrderType

  • USAddress

Items

Items.java 中:

  • Items 类是 primer.po 包的一部分。

  • 该类为 ItemsItemType 提供了公共接口。

  • 此类的实例化内容绑定到 XML ComplexTypes Items 及其子元素 ItemType

  • Item 提供了 getItem() 方法。

  • ItemType 提供了以下方法:

    • getPartNum();

    • setPartNum(String value);

    • getComment();

    • setComment(java.lang.String value);

    • getUSPrice();

    • setUSPrice(java.math.BigDecimal value);

    • getProductName();

    • setProductName(String value);

    • getShipDate();

    • setShipDate(java.util.Calendar value);

    • getQuantity();

    • setQuantity(java.math.BigInteger value);

ObjectFactory

ObjectFactory.java 中:

  • ObjectFactory 类是 primer.po 包的一部分。

  • ObjectFactory 提供了用于在 Java 内容树中实例化表示 XML 内容的 Java 接口的工厂方法。

  • 方法名是通过连接生成的:

    • 字符串常量 create

    • 所有外部 Java 类名称,如果 Java 内容接口嵌套在另一个接口中。

    • Java 内容接口的名称。

例如,在这种情况下,对于 Java 接口 primer.po.Items.ItemTypeObjectFactory 创建了方法 createItemsItemType()

PurchaseOrderType

PurchaseOrderType.java 中:

  • PurchaseOrderType 类是 primer.po 包的一部分。

  • 此类的实例化内容绑定到名为 PurchaseOrderType 的 XML 模式子元素。

  • PurchaseOrderType 是一个公共接口,提供以下方法:

    • getItems();

    • setItems(primer.po.Items value);

    • getOrderDate();

    • setOrderDate(java.util.Calendar value);

    • getComment();

    • setComment(java.lang.String value);

    • getBillTo();

    • setBillTo(primer.po.USAddress value);

    • getShipTo();

    • setShipTo(primer.po.USAddress value);

USAddress

USAddress.java 中:

  • USAddress 类是 primer.po 包的一部分。

  • 此类的实例化内容绑定到名为 USAddress 的 XML 模式元素。

  • USAddress 是一个公共接口,提供以下方法:

    • getState();

    • setState(String value);

    • getZip();

    • setZip(java.math.BigDecimal value);

    • getCountry();

    • setCountry(String value);

    • getCity();

    • setCity(String value);

    • getStreet();

    • setStreet(String value);

    • getName();

    • setName(String value);

基本示例

原文:docs.oracle.com/javase/tutorial/jaxb/intro/basic.html

本节描述了基本的 JAXB 示例(修改 Marshal、Unmarshal Validate),演示了如何:

  • 将 XML 文档解组为 Java 内容树,并访问其中包含的数据。

  • 修改 Java 内容树。

  • 使用 ObjectFactory 类创建 Java 内容树,然后将其编组为 XML 数据。

  • 在解组期间执行验证。

  • 在运行时验证 Java 内容树。

修改 Marshal 示例

修改 Marshal 示例演示了如何修改 Java 内容树。

  1. jaxb-ri-install/samples/modify-marshal/src/Main.java 类声明导入了三个标准 Java 类,五个 JAXB 绑定框架类和 primer.po 包:

    import java.io.FileInputStream;
    import java.io.IOException;
    import java.math.BigDecimal;
    
    import javax.xml.bind.JAXBContext;
    import javax.xml.bind.JAXBElement;
    import javax.xml.bind.JAXBException;
    import javax.xml.bind.Marshaller;
    import javax.xml.bind.Unmarshaller;
    
    import primer.po.*;
    
    
  2. 创建一个用于处理在 primer.po 中生成的类的 JAXBContext 实例。

    
    JAXBContext jc = JAXBContext.newInstance( "primer.po" );
    
    
  3. 创建一个 Unmarshaller 实例,并解组 po.xml 文件。

    Unmarshaller u = jc.createUnmarshaller();
    PurchaseOrder po = (PurchaseOrder)
        u.unmarshal(new FileInputStream("po.xml"));
    
    
  4. 使用 set 方法修改内容树中 address 分支中的信息。

    USAddress address = po.getBillTo();
    address.setName("John Bob");
    address.setStreet("242 Main Street");
    address.setCity("Beverly Hills");
    address.setState("CA");
    address.setZip(new BigDecimal
    address.setName("John Bob");
    address.setStreet("242 Main Street");
    address.setCity("Beverly Hills");
    address.setState("CA");
    address.setZip(new BigDecimal("90210"));
    
    
  5. 创建一个 Marshaller 实例,并将更新后的 XML 内容编组到 system.out。使用 setProperty API 指定输出编码;在本例中为格式化(易读)的 XML。

    Marshaller m = jc.createMarshaller();
    m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
    m.marshal(po, System.out);
    
    

使用 Ant 构建和运行修改 Marshal 示例

要使用 Ant 编译和运行修改 Marshal 示例,在终端窗口中,转到 jaxb-ri-install/samples/modify-marshal/ 目录,并输入以下内容:

ant

Unmarshal Validate 示例

Unmarshal Validate 示例演示了如何在解组期间启用验证。请注意,JAXB 提供了在解组期间进行验证但不在编组期间进行验证的功能。有关验证的更多详细信息,请参阅更多关于验证。

  1. jaxb-ri-install/samples/unmarshal-validate/src/Main.java 类声明导入了一个标准 Java 类,十一个 JAXB 绑定框架类和 primer.po 包:

    import java.io.File;
    
    import javax.xml.bind.JAXBContext;
    import javax.xml.bind.JAXBException;
    import javax.xml.bind.Marshaller;
    import javax.xml.bind.UnmarshalException;
    import javax.xml.bind.Unmarshaller;
    import javax.xml.bind.ValidationEvent;
    import javax.xml.bind.ValidationEventHandler;
    import javax.xml.bind.ValidationEventLocator;
    
    import static javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI;
    import javax.xml.validation.SchemaFactory;
    import javax.xml.validation.Schema;
    
    import primer.po.*;
    
    
  2. 创建一个用于处理在 primer.po 包中生成的类的 JAXBContext 实例。

    JAXBContext jc = JAXBContext.newInstance("primer.po");
    
    
  3. 创建一个 Unmarshaller 实例。

    Unmarshaller u = jc.createUnmarshaller();
    
    
  4. 默认的 JAXB Unmarshaller ValidationEventHandler 已启用,以将验证警告和错误发送到 system.out。默认配置导致在遇到第一个验证错误时解组操作失败。

    u.setValidating( true );
    
    
  5. 尝试将 po.xml 文件解组为 Java 内容树。在此示例中,po.xml 文件包含一个故意的错误。

    PurchaseOrder po = (PurchaseOrder)u.unmarshal(
        new FileInputStream("po.xml"));
    
    
  6. 默认验证事件处理程序处理验证错误,生成输出到 system.out,然后抛出异常。

    } catch( UnmarshalException ue ) {
        System.out.println("Caught UnmarshalException");
    } catch( JAXBException je ) { 
        je.printStackTrace();
    } catch( IOException ioe ) {
        ioe.printStackTrace();
    }
    
    

使用 Ant 构建和运行 Unmarshal Validate 示例。

要使用 Ant 编译和运行 Unmarshal Validate 示例,在终端窗口中,转到 jaxb-ri-install/samples/unmarshal-validate/ 目录,并输入以下内容:

ant 

自定义 JAXB 绑定

原文:docs.oracle.com/javase/tutorial/jaxb/intro/custom.html

以下部分描述了几个示例,这些示例是基于基本示例中演示的概念构建的。

本节的目标是演示如何使用自定义绑定声明来自定义 JAXB 绑定,可以通过以下两种方式之一进行:

  • 作为内联注释在 XML 模式中

  • 作为传递给 JAXB 绑定编译器的外部文件中的语句

与基本 JAXB 示例中的示例不同,该示例侧重于在生成基于模式的 Java 绑定类之前对 XML 模式进行的自定义。


注意: JAXB 绑定自定义目前必须手动完成。JAXB 技术的目标之一是标准化绑定声明的格式,从而可以创建自定义工具,并在 JAXB 实现之间提供标准的交换格式。


本节介绍了可以对 JAXB 绑定和验证方法进行的自定义。更多信息,请参见JAXB 规范。

为什么要自定义?

在大多数情况下,由 JAXB 绑定编译器生成的默认绑定就足够了。然而,有些情况下,您可能希望修改默认绑定。其中一些情况包括:

  • 为基于模式的 JAXB 包、类、方法和常量创建 API 文档:通过向您的模式添加自定义 Javadoc 工具注释,您可以解释与您的实现特定的概念、指南和规则。

  • 为默认的 XML 名称到 Java 标识符映射无法自动处理的情况提供语义上有意义的自定义名称;例如:

    • 为解决名称冲突(如 JAXB 规范 的附录 D.2.1 中所述)。请注意,JAXB 绑定编译器会检测并报告所有名称冲突。

    • 为类型安全枚举常量提供名称,这些名称不是有效的 Java 标识符;例如,枚举整数值。

    • 为未命名模型组的 Java 表示提供更好的名称,当它们绑定到 Java 属性或类时。

    • 提供比默认从目标命名空间 URI 派生的包名称更有意义的名称。

  • 覆盖默认绑定;例如:

    • 指定模型组必须绑定到类而不是列表。

    • 指定一个固定属性可以绑定到一个 Java 常量。

    • 覆盖 XML 模式内置数据类型到 Java 数据类型的指定默认绑定。在某些情况下,您可能希望引入一个替代的 Java 类,该类可以表示内置 XML 模式数据类型的其他特征。

自定义概述

本节解释了一些核心的 JAXB 自定义概念:

  • 内联和外部自定义

  • 范围、继承和优先级

  • 自定义语法

  • 定制命名空间前缀

内联和外部定制

对默认 JAXB 绑定的定制以传递给 JAXB 绑定编译器的绑定声明的形式进行。这些绑定声明可以通过以下两种方式进行:

  • 作为源 XML 模式中的内联注释

  • 作为外部绑定定制文件中的声明

对于一些人来说,使用内联定制更容易,因为您可以在应用于的模式的上下文中看到您的定制。相反,使用外部绑定定制文件使您能够定制 JAXB 绑定而无需修改源模式,并且使您能够轻松地将定制应用于多个模式文件。


注意: 您可以结合两种类型的定制。例如,您可以在内联注释中包含对外部绑定定制文件的引用。但是,您不能在同一模式元素上同时声明内联和外部定制。


这些类型的定制在以下各节中有更详细的描述:

内联定制

通过在 XML 模式文件中使用内联绑定声明进行的 JAXB 绑定定制采用了嵌入在模式<xsd:annotation>元素中的<xsd:appinfo>元素的形式(xsd:是 XML 模式命名空间前缀,在 W3C XML Schema Part 1: Structures中定义)。内联定制的一般形式如下例所示:

<xs:annotation>
    <xs:appinfo>
        <!--
        ...
        binding declarations     .
        ...
        -->
    </xs:appinfo>
</xs:annotation>

定制是应用在模式中声明的位置。例如,对特定元素级别的声明仅适用于该元素。请注意,必须在<annotation><appinfo>声明标签中使用 XML 模式命名空间前缀。在前面的例子中,xs:被用作命名空间前缀,因此声明被标记为<xs:annotation><xs:appinfo>

外部绑定定制文件

通过使用包含绑定声明的外部文件进行的 JAXB 绑定定制,采用了以下示例中显示的一般形式:

<jxb:bindings schemaLocation = "xs:anyURI">
    <jxb:bindings node = "xs:string">*
        <!-- binding declaration -->
    <jxb:bindings>
</jxb:bindings>

  • schemaLocation是指向远程模式的 URI 引用。

  • node是一个 XPath 1.0 表达式,用于标识与给定绑定声明相关联的schemaLocation中的模式节点。

例如,在 JAXB 绑定声明文件中,第一个schemaLocation/node声明指定了模式名称和根模式节点:

<jxb:bindings schemaLocation="po.xsd" node="/xs:schema">
</jxb:bindings>

后续的schemaLocation/node声明,例如前一个模式示例中名为ZipCodeTypesimpleType元素,采用以下形式:

<jxb:bindings node="//xs:simpleType [@name=’ZipCodeType’]">

绑定定制文件格式

绑定定制文件必须是 ASCII 文本。名称或扩展名并不重要;尽管在本章中使用的典型扩展名是.xjb

将定制文件传递给 JAXB 绑定编译器

包含绑定声明的定制文件通过以下语法传递给 JAXB 绑定编译器xjc

xjc -b file schema

其中file是绑定自定义文件的名称,schema是要传递给绑定编译器的模式的名称。

您可以拥有一个包含多个模式的自定义的单个绑定文件,或者您可以将自定义分成多个绑定文件;例如:

xjc schema1.xsd schema2.xsd schema3.xsd \
    -b bindings123.xjb
xjc schema1.xsd schema2.xsd schema3.xsd \
    -b bindings1.xjb \
    -b bindings2.xjb \
    -b bindings3.xjb

请注意,命令行上模式文件和绑定文件的顺序无关紧要;尽管每个绑定自定义文件在命令行上必须在其自己的-b开关之前。

有关xjc编译器选项的更多信息,请参见 JAXB 编译器选项。

外部绑定自定义的限制

有几条规则适用于在外部绑定自定义文件中进行的绑定声明,而不适用于在源模式中内联进行的类似声明:

  • 绑定自定义文件必须以jxb:bindings version属性开头,以及 JAXB 和 XMLSchema 命名空间的属性:

    <jxb:bindings version="1.0" 
    
        >
    
    
  • 绑定声明适用的远程模式必须通过使用jxb:bindings声明明确在 XPath 表示法中标识,指定schemaLocationnode属性:

    • schemaLocation指定远程模式的 URI 引用。

    • node指定一个 XPath 1.0 表达式,用于标识schemaLocation中的模式节点,给定的绑定声明与之相关联;在绑定自定义文件中的初始jxb:bindings声明的情况下,此节点通常为"/xs:schema"

同样,必须使用 XPath 表示法指定要应用自定义的模式中的各个节点;例如:

<jxb:bindings node="//xs:complexType [@name=’USAddress’]">

在这种情况下,绑定编译器将自定义应用于节点,就好像声明被嵌入在节点的<xs:appinfo>元素中一样。

总结这些规则,外部绑定元素<jxb:bindings>仅在以下三种情况下被 JAXB 绑定编译器识别并处理:

  • 当其父元素是<xs:appinfo>元素时。

  • 当它是另一个<jxb:bindings>元素的祖先时。

  • 当它是文档的根元素时。将<jxb:bindings>元素作为其根的 XML 文档称为外部绑定声明文件。

范围、继承和优先级

默认的 JAXB 绑定可以在四个不同级别或范围上进行自定义或覆盖。

以下图示了自定义声明的继承和优先级。具体来说,金字塔顶部的声明继承并取代下面的声明。

组件声明继承并取代定义声明;定义声明继承并取代模式声明;模式声明继承并取代全局声明。

图:自定义范围继承和优先级

自定义范围继承和优先级

自定义语法

JAXB 绑定声明的四种类型的语法,XML 到 Java 数据类型绑定声明的语法,以及自定义命名空间前缀的语法在以下部分中描述。

  • 全局绑定声明

  • 模式绑定声明

  • 类绑定声明

  • 属性绑定声明

  • javaType 绑定声明

  • Typesafe 枚举绑定声明

  • javadoc 绑定声明

全局绑定声明

全局范围的自定义使用 <globalBindings> 声明。全局范围自定义的语法如下:

<globalBindings>
    [ collectionType = "collectionType" ]
    [ fixedAttributeAsConstantProperty = "true" | "false" | "1" | "0" ]
    [ generateIsSetMethod = "true" | "false" | "1" | "0" ]
    [ enableFailFastCheck = "true" | "false" | "1" | "0" ]
    [ choiceContentProperty = "true" | "false" | "1" | "0" ]
    [ underscoreBinding = "asWordSeparator" | "asCharInWord" ]
    [ typesafeEnumBase = "typesafeEnumBase" ]
    [ typesafeEnumMemberName = "generateName" | "generateError" ]
    [ enableJavaNamingConventions = "true" | "false" 
    | "1" | "0" ]
    [ bindingStyle = "elementBinding" | "modelGroupBinding" ]
    [ <javaType> ... </javaType> ]*
</globalBindings>

  • collectionType 可以是 indexed 或实现 java.util.List 的任何完全限定类名。

  • fixedAttributeAsConstantProperty 可以是 true, false, 1, 或 0。默认值为 false

  • generateIsSetMethod 可以是 true, false, 1, 或 0。默认值为 false

  • enableFailFastCheck 可以是 true, false, 1, 或 0。如果 enableFailFastChecktrue1,并且 JAXB 实现支持此可选检查,那么在设置属性时将执行类型约束检查。默认值为 false。请注意,JAXB 实现不支持快速失败验证。

  • choiceContentProperty 可以是 true, false, 1, 或 0。默认值为 false。当 bindingStyleelementBinding 时,choiceContentProperty 不相关。因此,如果指定 bindingStyleelementBinding,那么 choiceContentProperty 必须导致无效的自定义。

  • underscoreBinding 可以是 asWordSeparatorasCharInWord。默认值为 asWordSeparator

  • typesafeEnumBase 可以是一组 QNames,每个都必须解析为简单类型定义。默认值为 xs:NCName。有关将 simpleType 定义本地化映射到 Java typesafe enum 类的信息,请参见 Typesafe 枚举绑定声明。

  • typesafeEnumMemberName 可以是 generateErrorgenerateName。默认值为 generateError

  • enableJavaNamingConventions 可以是 true, false, 1, 或 0。默认值为 true

  • bindingStyle 可以是 elementBindingmodelGroupBinding。默认值为 elementBinding

  • <javaType> 可以是零个或多个 javaType 绑定声明。有关更多信息,请参见 javaType 绑定声明。

<globalBindings> 声明仅在顶层 schema 元素的 annotation 元素中有效。在任何给定的模式或绑定声明文件中只能有一个 <globalBindings> 声明的实例。如果一个源模式包含或导入第二个源模式,则 <globalBindings> 声明必须在第一个源模式中声明。

模式绑定声明

模式范围的自定义使用 <schemaBindings> 声明。模式范围自定义的语法如下:

<schemaBindings>
[ <package> package </package> ]
[ <nameXmlTransform> ... </nameXmlTransform> ]*
</schemaBindings>

<package 
    [ name = "packageName" ]
    [ <javadoc> ... </javadoc> ]
</package>

<nameXmlTransform>
[ <typeName 
    [ suffix="suffix" ]
    [ prefix="prefix" ] /> ]
[ <elementName 
    [ suffix="suffix" ]
    [ prefix="prefix" ] /> ]
[ <modelGroupName 
    [ suffix="suffix" ]
    [ prefix="prefix" ] /> ]
[ <anonymousTypeName 
    [ suffix="suffix" ]
    [ prefix="prefix" ] /> ]
</nameXmlTransform>

如上所示,<schemaBinding> 声明包括两个子组件:

  • <package>...</package> 指定了包的名称,如果需要的话,还可以指定模式派生类的 API 文档的位置。

  • <nameXmlTransform>...</nameXmlTransform> 指定要应用的自定义。

类绑定声明

<class> 绑定声明使您能够自定义模式元素与 Java 内容接口或 Java Element 接口的绑定。<class> 声明可用于自定义:

  • 用于模式派生的 Java 接口的名称

  • 用于模式派生的 Java 内容接口的实现类

<class> 自定义的语法是:

<class 
    [ name = "className"]
    [ implClass= "implClass" ] >
    [ <javadoc> ... </javadoc> ]
</class>

  • name 是派生 Java 接口的名称。它必须是有效的 Java 接口名称,不能包含包前缀。包前缀从当前包的值继承。

  • implClassclassName 的实现类的名称,必须包含完整的包名称。

  • <javadoc> 元素为模式派生的 Java 接口指定了 Javadoc 工具注释。在此输入的字符串必须使用 CDATA< 来转义嵌入的 HTML 标记。

属性绑定声明

<property> 绑定声明使您能够自定义 XML 模式元素与其 Java 表示作为属性的绑定。自定义的范围可以是在定义级别或组件级别,具体取决于 <property> 绑定声明的指定位置。

<property> 自定义的语法是:

<property
    [ name = "propertyName"]
    [ collectionType = "propertyCollectionType" ]
    [ fixedAttributeAsConstantProperty = "true" |
    "false" | "1" | "0" ]
    [ generateIsSetMethod = "true" | 
    "false" | "1" | "0" ]
    [ enableFailFastCheck ="true" | 
    "false" | "1" | "0" ]
    [ <baseType> ... </baseType> ]
    [ <javadoc> ... </javadoc> ]
</property>

<baseType>
    <javaType> ... </javaType>
</baseType>

  • name 定义了自定义值 propertyName;它必须是有效的 Java 标识符。

  • collectionType 定义了自定义值 propertyCollectionType,即属性的集合类型 propertyCollectionType。如果指定,属性可以是 indexed 或任何实现 java.util.List 的完全限定类名。

  • fixedAttributeAsConstantProperty 定义了自定义值 fixedAttributeAsConstantProperty。该值可以是 truefalse10

  • generateIsSetMethod 定义了自定义值 generateIsSetMethod。该值可以是 truefalse10

  • enableFailFastCheck 定义了自定义值 enableFailFastCheck。该值可以是 truefalse10。请注意,JAXB 实现不支持快速失败验证。

  • <javadoc> 自定义了属性的 getter 方法的 Javadoc 工具注释。

javaType 绑定声明

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

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

  • parseMethod 在解组过程中被调用,将输入文档中的字符串转换为目标 Java 数据类型的值。

  • 在组合过程中,printMethod 被调用以将目标类型的值转换为词法表示。

如果您更喜欢定义自己的数据类型转换,JAXB 定义了一个静态类 DatatypeConverter,以帮助解析和打印 XML Schema 内置数据类型的有效词法表示。

<javaType> 自定义的语法为:

<javaType name= "*javaType*"
    [ xmlType= "*xmlType*" ]
    [ hasNsContext = "true" | "false" ]
    [ parseMethod= "*parseMethod*" ]
    [ printMethod= "*printMethod*" ]>

  • name 是要将 xmlType 绑定到的 Java 数据类型。

  • xmlType 是要将 javaType 绑定到的 XML Schema 数据类型的名称;当 <javaType> 声明的父级为 <globalBindings> 时,此属性是必需的。

  • hasNsContext 允许指定命名空间上下文作为打印或解析方法的第二个参数;可以是 truefalse10。默认情况下,此属性为 false,在大多数情况下,无需更改。

  • parseMethod 是在解组过程中调用的解析方法的名称。

  • printMethod 是在组合过程中调用的打印方法的名称。

<javaType> 声明可用于:

  • 一个 <globalBindings> 声明

  • 用于简单类型定义、GlobalBindings<basetype> 声明的注释元素

  • 一个 <property> 声明

请参见MyDatatypeConverter 类 ,了解在自定义数据类型转换器类中如何实现 <javaType> 声明和 DatatypeConverterInterface 接口的示例。

类型安全枚举绑定声明

类型安全枚举声明提供了一种将 XML simpleType 元素映射到 Java typesafe enum 类的本地化方式。您可以进行两种类型的类型安全枚举声明:

  • <typesafeEnumClass> 允许您将整个 simpleType 类映射到 typesafe enum 类。

  • <typesafeEnumMember> 允许您将 simpleType 类的选定成员映射到 typesafe enum 类。

在这两种情况下,对此类型的自定义有两个主要限制:

  • 只有具有枚举约束的 simpleType 定义才能使用此绑定声明进行自定义。

  • 此自定义仅适用于一次仅有一个 simpleType 定义。要在全局级别映射一组相似的 simpleType 定义,请在 <globalBindings> 声明中使用 typesafeEnumBase 属性,如全局绑定声明中所述。

<typesafeEnumClass> 自定义的语法为:

<typesafeEnumClass 
    [ name = "enumClassName" ]
    [ <typesafeEnumMember> ... </typesafeEnumMember> ]*
    [ <javadoc> enumClassJavadoc </javadoc> ]
</typesafeEnumClass>

  • name 必须是有效的 Java 标识符,并且不能有包前缀。

  • 您可以在<typesafeEnumClass>声明中嵌入零个或多个<typesafeEnumMember>声明。

  • <javadoc>定制了枚举类的 Javadoc 工具注释。

<typesafeEnumMember>定制的语法是:

<typesafeEnumMember 
    name = "enumMemberName">
    [ value = "enumMemberValue" ]
    [ <javadoc> enumMemberJavadoc </javadoc> ]
</typesafeEnumMember>

  • name必须始终指定,并且必须是有效的 Java 标识符。

  • value必须是源模式中指定的枚举值。

  • <javadoc>定制了枚举常量的 Javadoc 工具注释。

对于内联注释,必须在<simpleType>元素的注释元素中指定<typesafeEnumClass>声明。必须在枚举成员的注释元素中指定<typesafeEnumMember>。这使得枚举成员可以独立于枚举类进行定制。

有关类型安全枚举设计模式的信息,请参阅Joshua Bloch 的Effective Java Programming在 Oracle Technology Network 上的示例章节。。

javadoc 绑定声明

<javadoc>声明允许您向基于模式的 JAXB 包、类、接口、方法和字段添加自定义 Javadoc 工具注释。请注意,<javadoc>声明不能全局应用;它们只能作为其他绑定定制的子元素有效。

<javadoc>定制的语法是:

<javadoc>
    Contents in <b>Javadoc<\b> format.
</javadoc>

<javadoc>
    <<![CDATA[Contents in <b>Javadoc<\b> format ]]>
</javadoc>

请注意,应用于包级别的<javadoc>声明中的文档字符串必须包含<body>开放和关闭标签;例如:

<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,展示了处理自定义数据类型转换的<javaType>定制中的打印和解析方法。

总结这个示例:

  1. po.xsd是一个包含内联绑定定制的 XML 模式。

  2. MyDatatypeConverter.java 是一个 Java 类文件,实现了 po.xsd<javaType> 自定义中指定的打印和解析方法。

  3. Main.java 是自定义内联示例中的主要类文件,使用了由 JAXB 编译器生成的模式派生类。

使用 Ant 构建和运行自定义内联示例

要使用 Ant 编译和运行自定义内联示例,在终端窗口中,转到 jaxb-ri-install/samples/inline-customize/ 目录并输入以下内容:

ant 

此示例中的关键自定义和自定义的 MyDatatypeConverter.java 类在下一节中有更详细的描述。

自定义模式

在自定义内联示例中使用的自定义模式位于文件 jaxb-ri-install/samples/inline-customize/po.xsd 中。自定义内容位于 <xsd:annotation> 标签中。

全局绑定声明

以下代码示例显示了 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>

  • <jxb:package name="primer.myPo"/> 指定 primer.myPo 作为生成模式派生类的包。

  • <jxb:nameXmlTransform>指定所有生成的 Java 元素接口默认附加Element到生成的名称。例如,当针对此模式运行 JAXB 编译器时,将生成元素接口CommentElementPurchaseOrderElement。相比之下,没有此自定义, 默认绑定会生成CommentPurchaseOrder。如果模式在不同的符号空间中使用相同的名称,例如在全局元素和类型定义中,此自定义可帮助您解决冲突,而不必使用单独的绑定声明逐个解决每个冲突。

  • <jxb:javadoc>指定了primer.myPo包的自定义 Javadoc 工具注释。请注意,与在类级别显示的<javadoc>声明不同,当在包级别进行<javadoc>声明时,必须包含开头和结尾的<body>标签。

类绑定声明

以下代码显示了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 工具注释将包含描述"一个&lt;b>采购订单&lt;/b>包括地址和商品。" 其中&lt;用于转义<b> HTML 标签中的开括号。


注意: 当在complexType定义的appinfo元素中指定<class>自定义时,如前面的示例所示,complexType定义将绑定到 Java 内容接口。


po.xsd中,另一个<javadoc>自定义在此类级别声明,但这次使用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>


注意: 如果要在<jaxb:javadoc>自定义中包含 HTML 标签,必须将数据放在CDATA部分中或使用&lt;转义所有左尖括号。有关更多信息,请参阅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 数据类型之间的转换的方法,使用<javaType>自定义。

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 中的 <javaType> 声明中引用 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。还要注意,因为 <jxb:javaType name="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>

JAXB 版本号

具有根元素 <jaxb:bindings> 的 XML 文件被视为外部绑定文件。根元素必须指定其绑定声明必须遵守的 JAXB 版本属性;具体来说,根 <jxb:bindings> 元素必须包含 <jxb:version> 声明或 version 属性。相比之下,当进行内联绑定声明时,JAXB 版本号作为 <xsd:schema> 声明的属性:

<xsd:schema 

    jxb:version="1.0">

命名空间声明

如 JAXB 版本、命名空间和模式属性中所示,外部绑定声明文件中的命名空间声明包括 JAXB 命名空间和 XMLSchema 命名空间。请注意,此示例中使用的前缀实际上可以是任何您想要的;重要的是在文件中后续声明中一致使用您在此定义的任何前缀。

模式名称和模式节点

代码中的第四行在 JAXB 版本、命名空间和模式属性中指定了此绑定声明文件适用的模式的名称,以及首次生效的模式节点。此文件中的后续绑定声明可以引用模式中的特定节点,但此第一个声明应该涵盖整个模式;例如,在bindings.xjb中:

<jxb:bindings schemaLocation="po.xsd" node="/xs:schema">

全局和模式绑定声明

bindings.xjb中的全局模式绑定声明与数据类型转换器示例中的po.xsd中的相同。唯一的区别是,因为po.xsd中的声明是内联完成的,您必须将它们嵌入到<xs:appinfo>元素中,而这些元素又嵌入到<xs:annotation>元素中。以这种方式嵌入声明在外部绑定文件中是不必要的。

<jxb:globalBindings
    fixedAttributeAsConstantProperty="true"
    collectionType="java.util.Vector"
    typesafeEnumBase="xs:NCName"
    choiceContentProperty="false"
    typesafeEnumMemberName="generateError"
    bindingStyle="elementBinding"
    enableFailFastCheck="false"
    generateIsSetMethod="false"
    underscoreBinding="asCharInWord"/>
    <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>

相比之下,数据类型转换器示例中po.xsd中使用的语法是:

<xsd:annotation>
    <xsd:appinfo>
        <jxb:globalBindings
            ...
            *binding-declarations*
            ...
        <jxb:schemaBindings>
            ...
            *binding-declarations*
            ...
        </jxb:schemaBindings>
    </xsd:appinfo>
</xsd:annotation>

类声明

bindings.xjb中的类级绑定声明与数据类型转换器示例中的po.xsd中的类似声明有两个不同之处:

  • bindings.xjb中的所有其他绑定声明一样,您不需要将自定义嵌入到模式<xsd:appinfo>元素中。

  • 您必须指定应用自定义的模式节点。此类型声明的一般语法为:

    <jxb:bindings node="//*node-type*[@name=’*node-name*’]">
    
    

例如,以下代码显示了名为USAddresscomplexType的绑定声明。

<jxb:bindings node="//xs:complexType [@name=’USAddress’]">
    <jxb:class>
        <jxb:javadoc>
            <![CDATA[
                First line of documentation for a <b>USAddress</b>.
            ]]>
        </jxb:javadoc>
    </jxb:class>

<jxb:bindings node=".//xs:element [@name=’name’]">
    <jxb:property name="toName"/>
</jxb:bindings>

<jxb:bindings node=".//xs:element [@name=’zip’]">
    <jxb:property name="zipCode"/>
</jxb:bindings>
</jxb:bindings>
<!-- 
    node="//xs:complexType
    [@name=’USAddress’]" -->

请注意,在此示例中,USAddress是子元素namezip的父元素,因此</jxb:bindings>标签将子元素和类级javadoc声明的bindings声明括起来。

外部自定义示例

外部自定义示例与数据类型转换器示例相同,只是外部自定义示例中的绑定声明是使用外部绑定声明文件而不是内联在源 XML 模式中完成的。

外部自定义示例中使用的绑定自定义文件是jaxb-ri-install/samples/external-customize/binding.xjb

本节将bindings.xjb中的自定义声明与 XML 模式po.xsd中的数据类型转换器示例中使用的类似声明进行比较。这两组声明实现完全相同的结果。

使用 Ant 构建和运行外部自定义示例

要使用 Ant 编译和运行外部自定义示例,在终端窗口中,转到jaxb-ri-install/samples/external-customize/目录,并输入以下内容:

ant

Java-to-Schema 示例

原文:docs.oracle.com/javase/tutorial/jaxb/intro/j2schema.html

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

j2s-create-marshal 示例

j2s-create-marshal 示例演示了 Java-to-schema 数据绑定。它演示了对带有 JAXB 注解的类进行编组和解组,并展示了如何在解组时使用从 JAXB 映射类生成的模式文件启用 JAXP 1.3 验证。

schema 文件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注解为使用int作为键和String作为值的HashMap(字段)提供自定义映射的 XML 内容的组合和解组。

接口XmlAdapter和注解@XmlJavaTypeAdapter用于在解组和组合期间对数据类型进行特殊处理。有各种 XML 数据类型,其表示方式不容易映射到 Java(例如,xs:DateTimexs:Duration),以及 Java 类型不正确地映射到 XML 表示。例如,java.util.Collection(如List)和java.util.Map(如HashMap)的实现,或非 JavaBean 类。

为这类情况提供了XmlAdapter接口和@XmlJavaTypeAdapter注解。这种组合提供了一个可移植的机制,用于将 XML 内容读取和写入 Java 应用程序。

XmlAdapter接口定义了数据读取和写入的方法。

/*
 *  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);
}

您可以使用@XmlJavaTypeAdapter注解将特定的XmlAdapter实现与Target类型PACKAGEFIELDMETHODTYPEPARAMETER关联。

j2s-xmlAdapter 示例展示了如何使用XmlAdapter将 XML 内容映射到(自定义)HashMap中并从中组合出来。类KitchenWorldBasket中的HashMap对象basket使用int类型的键和String类型的值。这些数据类型应该反映在读取和写入的 XML 内容中,因此 XML 内容应如下示例所示:

<basket>
    <entry key="9027">glasstop stove in black</entry>
    <entry key="288">wooden spoon</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>glasstop stove in black</value>
    </entry>
    <entry>
        <key>288</key>
        <value>wooden spoon</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上进行任何对应的组合或解组操作时,将调用AdapterPurchaseListToHashMap的组合或解组方法。

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

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

ant

j2s-xmlAttribute 示例

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

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

  • 静态最终字段映射到 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 示例展示了如何在静态最终字段上使用@XmlAttribute注解,在字段而不是相应的 bean 方法上使用,在 bean 属性(方法)上使用,以及在不是集合类型的字段上使用。在类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注解将类或enum类型映射到 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 类示例展示了如何在包级别、字段和属性上使用@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

更多信息

原文:docs.oracle.com/javase/tutorial/jaxb/intro/info.html

有关 JAXB、XML 和 XML Schema 的更多信息,请参见:

  • Java 社区进程页面:

    jcp.org/en/jsr/detail?id=222

  • W3C 推荐的“可扩展标记语言(XML)1.0”:

    www.w3.org/TR/REC-xml

  • XML 信息集:

    www.w3.org/TR/xml-infoset/

  • 由大卫·C·法尔赛德编辑的 W3C XML Schema 第 0 部分:入门指南:

    www.w3.org/TR/xmlschema-0/

  • 由詹姆斯·克拉克和史蒂夫·德罗斯编辑的 XML 路径语言:

    www.w3.org/TR/1999/REC-xpath-19991116