您应该为 RESTful Web 服务使用 JAXB 生成的类

一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡/ 赠书活动

目前,正在 星球 内带小伙伴们做第一个项目:全栈前后端分离博客项目,采用技术栈 Spring Boot + Mybatis Plus + Vue 3.x + Vite 4手把手,前端 + 后端全栈开发,从 0 到 1 讲解每个功能点开发步骤,1v1 答疑,陪伴式直到项目上线,目前已更新了 204 小节,累计 32w+ 字,讲解图:1416 张,还在持续爆肝中,后续还会上新更多项目,目标是将 Java 领域典型的项目都整上,如秒杀系统、在线商城、IM 即时通讯、权限管理等等,已有 870+ 小伙伴加入,欢迎点击围观

我记得在 20 世纪 90 年代末/2000 年初,编程领域的所有热门话题都是关于 XML 的。所有“专家”都说您必须使用 XML 进行数据交换。 XML 确实有很多好处。但在今天的编程中,XML 常常被视为“老派”或限制性太强。 XML 确实很难处理。许多开发人员(包括我自己)在选择时会使用 JSON 而不是 XML。 JSON 比 XML 宽容得多,这使得它更易于使用。

虽然 XML 可能有点过时,但它仍然很好用。即使您正在执行基于 JSON 的 Restful Web 服务。

Spring 中的 Restful Web 服务

我不会在这篇文章中介绍在 Spring 中构建 Restful Web 服务。那是以后的话题。但是当你使用 Spring MVC 开发 Restful Web Services 时,你可以设置很多灵活性。我通常设计我的 Web 服务,以便客户端可以使用 JSON 或 XML。标准支持这一点,而且这很容易做到。

您将在 Internet 上看到的许多示例都是从使用 JAXB 注释的 Java POJO 开始的。这行得通,但我也觉得这是一个错误。 Web 服务的“合同”现在是一个 Java 类。这可能对你有用,但它不可移植。如果您的一位客户使用 PHP 编写代码怎么办? JAXB 注释的 Java 类对他们来说毫无用处。

XML模式

XML Schema 是描述 XML 文档的规范。将其视为 XML 文档的强类型。您可以指定属性(如果它们可以为空)、它们的数据类型、它们是否可以是列表等。XML 模式的功能非常强大。

JAXB 的一个非常酷的特性是您可以从 XML 模式文档生成 JAXB 注释的 Java POJO。当您这样做时,您现在就拥有了一个适用于您的 Web 服务数据类型的可移植契约。您的“合同”不再与 Java 编程语言相关联。您可以将 XML 模式提供给使用另一种编程语言(例如 C#)为您的 Web 服务构建客户端的人,他们可以使用 XML 模式为客户端生成代码。

XML Schema 是一种被广泛接受的标准,不依赖于特定的编程语言。通过使用 XML 模式并将其提供给您的客户,您可以使 Restful Web 服务更易于使用。您的客户对他们需要发送的内容有一个标准化的规范。

JAXB 为 Restful Web 服务生成的类

在本文中,我将向您展示如何设置 Maven 项目以创建由 JAXB 从 XML 模式生成的 Java 类的 Jar 文件。

在 IntelliJ 中生成 Maven 项目

出于本示例的目的,我将使用 IntelliJ 创建一个 Maven 项目。在实际使用中,您需要将其设置为独立的 Maven 项目或 Maven 模块。这将允许将 JAXB 生成的类捆绑在 JAR 文件中并在其他项目或模块中重用。

1. 在 IntelliJ 中新建一个项目。


2. 在 IntelliJ 的新建项目对话框中设置 GroupId 和 ArtifactId。


3. 选择项目在硬盘上的存储位置。


4. IntelliJ 会为您验证新目录的创建。单击确定。


5. 根据您在 IntelliJ 中的设置,您可能会被要求导入更改。由于性能原因,在处理大型复杂的 Maven 项目时,我经常关闭此功能。如果您看到此对话框,请单击“导入更改”。

6. 此时您已经在 IntelliJ 中创建了一个新的 Maven 项目。可以看到Maven标准目录结构已经创建。

创建 XML 模式

我们将创建的第一个文件是我们将使用的 XML 模式。假设我们正在创建一个 Web 服务来添加产品,并且需要一个创建产品命令对象。

在我们的 XML 模式中,我们正在创建一个 Product 类,以及一个 CreateProductRequest 类。这将扩展 ProductClass 并为 API 密钥添加一个字段。此文件位于文件夹 /main/resources 中。这是 XML 架构文件的默认位置。
jaxb.xsd


 <?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="2.0">
&lt;!--This tells JAXB what package to create the Java classes in--&gt;
&lt;xsd:annotation&gt;
    &lt;xsd:appinfo&gt;
        &lt;jaxb:schemaBindings&gt;
            &lt;jaxb:package name="guru.springframework.domain"/&gt;
        &lt;/jaxb:schemaBindings&gt;
    &lt;/xsd:appinfo&gt;
&lt;/xsd:annotation&gt;

&lt;xsd:complexType name="Product"&gt;
    &lt;xsd:sequence&gt;
        &lt;xsd:element name="productId" type="xsd:integer"/&gt;
        &lt;xsd:element name="productDescription" type="xsd:string"/&gt;
        &lt;xsd:element name="productPrice" type="xsd:decimal"/&gt;
    &lt;/xsd:sequence&gt;
&lt;/xsd:complexType&gt;

&lt;xsd:complexType name="CreateProductRequest"&gt;
    &lt;xsd:complexContent&gt;
        &lt;xsd:extension base="Product"&gt;
            &lt;xsd:attribute name="apikey" type="xsd:string"/&gt;
        &lt;/xsd:extension&gt;
    &lt;/xsd:complexContent&gt;
&lt;/xsd:complexType&gt;

</xsd:schema>

配置 Maven

在 IntelliJ 中创建项目为我们提供了一个非常基本的 Maven POM 文件。这是为我们创建的 Maven POM。


 <?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="2.0">
&lt;!--This tells JAXB what package to create the Java classes in--&gt;
&lt;xsd:annotation&gt;
    &lt;xsd:appinfo&gt;
        &lt;jaxb:schemaBindings&gt;
            &lt;jaxb:package name="guru.springframework.domain"/&gt;
        &lt;/jaxb:schemaBindings&gt;
    &lt;/xsd:appinfo&gt;
&lt;/xsd:annotation&gt;

&lt;xsd:complexType name="Product"&gt;
    &lt;xsd:sequence&gt;
        &lt;xsd:element name="productId" type="xsd:integer"/&gt;
        &lt;xsd:element name="productDescription" type="xsd:string"/&gt;
        &lt;xsd:element name="productPrice" type="xsd:decimal"/&gt;
    &lt;/xsd:sequence&gt;
&lt;/xsd:complexType&gt;

&lt;xsd:complexType name="CreateProductRequest"&gt;
    &lt;xsd:complexContent&gt;
        &lt;xsd:extension base="Product"&gt;
            &lt;xsd:attribute name="apikey" type="xsd:string"/&gt;
        &lt;/xsd:extension&gt;
    &lt;/xsd:complexContent&gt;
&lt;/xsd:complexType&gt;

</xsd:schema>

Maven 依赖项

我们需要向我们的 Maven POM 添加三个依赖项。第一个是 JAXB API,第二个是 JAXB 实现,最后第三个是 Maven JAXB 插件。


 <?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="2.0">
&lt;!--This tells JAXB what package to create the Java classes in--&gt;
&lt;xsd:annotation&gt;
    &lt;xsd:appinfo&gt;
        &lt;jaxb:schemaBindings&gt;
            &lt;jaxb:package name="guru.springframework.domain"/&gt;
        &lt;/jaxb:schemaBindings&gt;
    &lt;/xsd:appinfo&gt;
&lt;/xsd:annotation&gt;

&lt;xsd:complexType name="Product"&gt;
    &lt;xsd:sequence&gt;
        &lt;xsd:element name="productId" type="xsd:integer"/&gt;
        &lt;xsd:element name="productDescription" type="xsd:string"/&gt;
        &lt;xsd:element name="productPrice" type="xsd:decimal"/&gt;
    &lt;/xsd:sequence&gt;
&lt;/xsd:complexType&gt;

&lt;xsd:complexType name="CreateProductRequest"&gt;
    &lt;xsd:complexContent&gt;
        &lt;xsd:extension base="Product"&gt;
            &lt;xsd:attribute name="apikey" type="xsd:string"/&gt;
        &lt;/xsd:extension&gt;
    &lt;/xsd:complexContent&gt;
&lt;/xsd:complexType&gt;

</xsd:schema>

Maven JAXB 插件

接下来我们需要将 Maven 的 JAXB 插件配置到 Maven POM。


 <?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="2.0">
&lt;!--This tells JAXB what package to create the Java classes in--&gt;
&lt;xsd:annotation&gt;
    &lt;xsd:appinfo&gt;
        &lt;jaxb:schemaBindings&gt;
            &lt;jaxb:package name="guru.springframework.domain"/&gt;
        &lt;/jaxb:schemaBindings&gt;
    &lt;/xsd:appinfo&gt;
&lt;/xsd:annotation&gt;

&lt;xsd:complexType name="Product"&gt;
    &lt;xsd:sequence&gt;
        &lt;xsd:element name="productId" type="xsd:integer"/&gt;
        &lt;xsd:element name="productDescription" type="xsd:string"/&gt;
        &lt;xsd:element name="productPrice" type="xsd:decimal"/&gt;
    &lt;/xsd:sequence&gt;
&lt;/xsd:complexType&gt;

&lt;xsd:complexType name="CreateProductRequest"&gt;
    &lt;xsd:complexContent&gt;
        &lt;xsd:extension base="Product"&gt;
            &lt;xsd:attribute name="apikey" type="xsd:string"/&gt;
        &lt;/xsd:extension&gt;
    &lt;/xsd:complexContent&gt;
&lt;/xsd:complexType&gt;

</xsd:schema>

完整的 Maven POM

这是最终的 Maven POM。


 <?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="2.0">
&lt;!--This tells JAXB what package to create the Java classes in--&gt;
&lt;xsd:annotation&gt;
    &lt;xsd:appinfo&gt;
        &lt;jaxb:schemaBindings&gt;
            &lt;jaxb:package name="guru.springframework.domain"/&gt;
        &lt;/jaxb:schemaBindings&gt;
    &lt;/xsd:appinfo&gt;
&lt;/xsd:annotation&gt;

&lt;xsd:complexType name="Product"&gt;
    &lt;xsd:sequence&gt;
        &lt;xsd:element name="productId" type="xsd:integer"/&gt;
        &lt;xsd:element name="productDescription" type="xsd:string"/&gt;
        &lt;xsd:element name="productPrice" type="xsd:decimal"/&gt;
    &lt;/xsd:sequence&gt;
&lt;/xsd:complexType&gt;

&lt;xsd:complexType name="CreateProductRequest"&gt;
    &lt;xsd:complexContent&gt;
        &lt;xsd:extension base="Product"&gt;
            &lt;xsd:attribute name="apikey" type="xsd:string"/&gt;
        &lt;/xsd:extension&gt;
    &lt;/xsd:complexContent&gt;
&lt;/xsd:complexType&gt;

</xsd:schema>

构建我们的 JAXB Maven 项目

运行 Maven 包目标

IntelliJ 使使用 Maven 变得非常容易。在 IDE 的右侧,您会看到一个“Maven 项目”按钮,单击该按钮将打开“Maven 项目”对话框。要构建我们的项目,请在生命周期下双击“包”目标。

您应该会看到 Maven 运行并成功构建。


 <?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="2.0">
&lt;!--This tells JAXB what package to create the Java classes in--&gt;
&lt;xsd:annotation&gt;
    &lt;xsd:appinfo&gt;
        &lt;jaxb:schemaBindings&gt;
            &lt;jaxb:package name="guru.springframework.domain"/&gt;
        &lt;/jaxb:schemaBindings&gt;
    &lt;/xsd:appinfo&gt;
&lt;/xsd:annotation&gt;

&lt;xsd:complexType name="Product"&gt;
    &lt;xsd:sequence&gt;
        &lt;xsd:element name="productId" type="xsd:integer"/&gt;
        &lt;xsd:element name="productDescription" type="xsd:string"/&gt;
        &lt;xsd:element name="productPrice" type="xsd:decimal"/&gt;
    &lt;/xsd:sequence&gt;
&lt;/xsd:complexType&gt;

&lt;xsd:complexType name="CreateProductRequest"&gt;
    &lt;xsd:complexContent&gt;
        &lt;xsd:extension base="Product"&gt;
            &lt;xsd:attribute name="apikey" type="xsd:string"/&gt;
        &lt;/xsd:extension&gt;
    &lt;/xsd:complexContent&gt;
&lt;/xsd:complexType&gt;

</xsd:schema>

Maven 构建工件

Maven 将构建到“目标”目录中。您可以看到在 IntelliJ 中生成的 Java 类。

JAXB 生成的类

我们期望从我们定义的 XML 模式生成两个类。

产品.java


 <?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="2.0">
&lt;!--This tells JAXB what package to create the Java classes in--&gt;
&lt;xsd:annotation&gt;
    &lt;xsd:appinfo&gt;
        &lt;jaxb:schemaBindings&gt;
            &lt;jaxb:package name="guru.springframework.domain"/&gt;
        &lt;/jaxb:schemaBindings&gt;
    &lt;/xsd:appinfo&gt;
&lt;/xsd:annotation&gt;

&lt;xsd:complexType name="Product"&gt;
    &lt;xsd:sequence&gt;
        &lt;xsd:element name="productId" type="xsd:integer"/&gt;
        &lt;xsd:element name="productDescription" type="xsd:string"/&gt;
        &lt;xsd:element name="productPrice" type="xsd:decimal"/&gt;
    &lt;/xsd:sequence&gt;
&lt;/xsd:complexType&gt;

&lt;xsd:complexType name="CreateProductRequest"&gt;
    &lt;xsd:complexContent&gt;
        &lt;xsd:extension base="Product"&gt;
            &lt;xsd:attribute name="apikey" type="xsd:string"/&gt;
        &lt;/xsd:extension&gt;
    &lt;/xsd:complexContent&gt;
&lt;/xsd:complexType&gt;

</xsd:schema>

创建产品请求.java

注意这个类实际上是如何扩展 Product 类的。


 <?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="2.0">
&lt;!--This tells JAXB what package to create the Java classes in--&gt;
&lt;xsd:annotation&gt;
    &lt;xsd:appinfo&gt;
        &lt;jaxb:schemaBindings&gt;
            &lt;jaxb:package name="guru.springframework.domain"/&gt;
        &lt;/jaxb:schemaBindings&gt;
    &lt;/xsd:appinfo&gt;
&lt;/xsd:annotation&gt;

&lt;xsd:complexType name="Product"&gt;
    &lt;xsd:sequence&gt;
        &lt;xsd:element name="productId" type="xsd:integer"/&gt;
        &lt;xsd:element name="productDescription" type="xsd:string"/&gt;
        &lt;xsd:element name="productPrice" type="xsd:decimal"/&gt;
    &lt;/xsd:sequence&gt;
&lt;/xsd:complexType&gt;

&lt;xsd:complexType name="CreateProductRequest"&gt;
    &lt;xsd:complexContent&gt;
        &lt;xsd:extension base="Product"&gt;
            &lt;xsd:attribute name="apikey" type="xsd:string"/&gt;
        &lt;/xsd:extension&gt;
    &lt;/xsd:complexContent&gt;
&lt;/xsd:complexType&gt;

</xsd:schema>

结论

这只是一个使用 JAXB 和 Maven 从 XML 模式生成类的非常简单的示例。在本文中,我逐步向您展示了如何使用 XML 模式和 JAXB 生成 Java 类。生成的类被捆绑到一个 JAR 文件中,该文件是可移植的并且可以与其他 Java 项目共享。

作为一名 Spring Source 顾问,我在一家构建了许多 Restful API 的大公司工作。构建 API 的团队没有使用 JAXB 从 XML 模式生成类。相反,他们手动构建 JAXB 类,无法为他们的客户提供 XML 模式。作为他们 API 的使用者,配置我的数据类型并对其进行故障排除是一个耗时的过程。

我还在团队确实使用 XML 模式构建 API 的组织中做过咨询。拥有 XML 模式使得编写客户端代码变得轻而易举。

资源

日本航空航天局

您可以 在此处 找到 JAXB 项目的文档。

JAXB Maven 插件

我使用了 JAXB Maven 插件的默认设置。可以使用其他选项。 JAXB Maven 插件的文档在 此处

项目源代码

本教程中使用的源代码可在 Github 此处 获取。