4.3. 摘要到 Java 对象以及

用于通过 HTTP 传输的 Java 对象

使用 REST 协议的最常见方式之一是传输消息正文中 Java Bean 的内容。为了实现此工作,您需要有一个机制来汇总 Java 对象,以及从适当的数据格式放入其中。REST DSL 支持下列数据格式适用于编码 Java 对象:

JSON

JSON (JavaScript 对象表示法)是一个轻量级数据格式,可轻松从 Java 对象映射。JSON 语法是紧凑、轻便键入的,方便人进行读和写。因此,JSON 已成为 REST 服务的消息格式。

例如,以下 JSON 代码可以代表用户 bean,具有两个属性字段,即 idname

{
    "id" : 1234,
    "name" : "Jane Doe"
}
JAXB

JAXB (XML Binding 的 Java 架构)是基于 XML 的数据格式,可轻松映射到 Java 对象或从 Java 对象映射。要将 XML 接合到 Java 对象,还必须注解您要使用的 Java 类。

例如,以下 JAXB 代码可以代表用户 bean,其中有两个属性字段: idname

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<User>
  <Id>1234</Id>
  <Name>Jane Doe</Name>
</User>
注意

从 Camel 2.17.0 中,CIB 数据格式和类型转换支持从 XML 转换到 POJO,这些类使用 ObjectFactory 而不是 XmlRootElement。此外,camel 上下文应包含 CamelJaxbObjectFactory 属性,其值为 true。但是,由于优化,默认值为 false。

JSON 和 JAXB 与 REST DSL 集成

当然,您可以编写所需的代码,以将邮件正文转换为 Java 对象,并自行从 Java 对象转换。但是 REST DSL 提供了自动进行这个转换的便利。特别是,JSON 和 JAXB 与 REST DSL 的集成提供了以下优点:

  • 自动对 Java 对象和从 Java 对象编入和执行(授予适当的配置)。
  • REST DSL 可以自动检测数据格式(JSON 或 JAXB),并执行适当的转换。
  • REST DSL 提供了一个抽象层,以便您编写的代码不特定于特定的 JSON 或 JAXB 实施。因此,您可以稍后切换实施,对应用程序代码产生最小影响。

支持的数据格式组件

Apache Camel 提供 JSON 和 JAXB 数据格式的多个不同实施。REST DSL 目前支持以下数据格式:

  • JSON

    • jackson 数据格式(camel-jackson) (默认)
    • GSon 数据格式(camel-gson)
    • XStream 数据格式(camel-xstream)
  • JAXB

    • JAXB 数据格式(camel-jaxb)

如何启用对象 marshalling

要在 REST DSL 中启用对象摘要,请观察以下几点:

  1. 启用绑定模式,通过设置 bindingMode 选项(有几个级别可设置绑定模式)。如需详情,请参阅 “配置绑定模式”一节
  2. 使用 type 选项(必需)以及带有 outType 选项(可选)的传出消息上指定要转换为的 Java 类型(或从中)。
  3. 如果要将 Java 对象转换为 JAXB 数据格式,您必须记得使用适当的 JAXB 注释给 Java 类添加注解。
  4. 指定底层数据格式实现(或实现),使用 jsonDataFormat 选项和/或 xmlDataFormat 选项(可以在 restConfiguration 构建器中指定)。
  5. 如果您的路由以 JAXB 格式提供返回值,则通常您希望将交换正文的 Out 消息设置为带有 JAXB 注释(a JAXB 元素)的类实例。如果您希望以 XML 格式直接提供 JAXB 返回值,但是,使用键 xml.out.mustBeJAXBElementdataFormatProperty 设置为 false (可以在 restConfiguration 构建器中指定)。例如,在 XML DSL 语法中:

    <restConfiguration ...>
      <dataFormatProperty key="xml.out.mustBeJAXBElement"
                          value="false"/>
      ...
    </restConfiguration>
  6. 将所需的依赖项添加到项目构建文件中。例如,如果您使用 Maven 构建系统,且您使用 Jackson 数据格式,您要将以下依赖项添加到 Maven POM 文件中:

    <?xml version="1.0" encoding="UTF-8"?>
    <project ...>
      ...
      <dependencies>
        ...
        <!-- use for json binding --> <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-jackson</artifactId> </dependency>
        ...
      </dependencies>
    </project>
  7. 将应用程序部署到 OSGi 容器时,请记得为您的所选数据格式安装必要的功能。例如,如果您使用的是 Jackson 数据格式(默认),则通过输入以下命令来安装 camel-jackson 功能:

    JBossFuse:karaf@root> features:install camel-jackson

    或者,如果您部署到 Fabric 环境,您可以将该功能添加到 Fabric 配置集中。例如,如果您使用配置集 MyRestProfile,您可以通过输入以下命令来添加该功能:

    JBossFuse:karaf@root> fabric:profile-edit --features camel-jackson MyRestProfile

配置绑定模式

默认情况下,bindingMode 选项是 off,因此您必须明确配置它,以便能启用 Java 对象的 marshalling。TABLE 显示支持的绑定模式列表。

注意

仅当 content-type 标头包含 jsonxml 的绑定时,从 POJO 到 JSon/JAXB 的绑定才会进行 Camel 2.16.3。如果消息正文不应尝试使用绑定进行总结,这允许您指定自定义内容类型。例如,当消息正文是一个自定义二进制有效负载时,这很有用。

表 4.2. REST DSL BInding 模式

绑定模式描述

off

关闭绑定 (默认)

auto

为 JSON 和/或 XML 启用绑定。在这个模式中,Camel 会自动根据传入消息的格式自动选择 JSON 或 XML(JAXB)。您不需要 同时启用两种数据格式:JSON 实现、XML 实现,或两者都可以在类路径中提供。

json

仅为 JSON 启用了绑定。必须在 classpath 上提供 JSON 实施(默认为 Camel 尝试启用 camel-jackson 实施)。

xml

仅为 XML 启用绑定。必须在 classpath 上提供一个 XML 实现(默认为 Camel 尝试启用 camel-jaxb 实现)。

json_xml

为 JSON 和 XML 启用了绑定。在这个模式中,Camel 会自动根据传入消息的格式自动选择 JSON 或 XML(JAXB)。您需要在 classpath 上提供两种数据类型。

在 Java 中,这些绑定模式值表示为以下枚举类型的实例:

org.apache.camel.model.rest.RestBindingMode

您可以设置 bindingMode 的不同级别,如下所示:

REST DSL 配置

您可以在 restConfiguration 构建器中设置 bindingMode 选项,如下所示:

restConfiguration().component("servlet").port(8181).bindingMode(RestBindingMode.json);
服务定义基础部分

您可以在 rest() 关键字后设置 bindingMode 选项(在 verb 子句之前),如下所示:

rest("/user").bindingMode(RestBindingMode.json).get("/{id}").VerbClause
verb 子句

您可以在 verb 子句中设置 bindingMode 选项,如下所示:

rest("/user")
    .get("/{id}").bindingMode(RestBindingMode.json).to("...");

示例

如需完整的代码示例,显示如何使用 REST DSL 将 Servlet 组件用作 REST 实施,了解 Apache Camel camel-example-servlet-rest-blueprint 示例。您可以通过安装独立 Apache Camel 发行版 apache-camel-2.23.2 找到这个示例。fuse-7_10_0-00018-redhat-00001.zip,它包括在 Fuse 安装的额外s / 子目录中。

安装独立 Apache Camel 发行版后,您可以在以下目录中找到示例代码:

ApacheCamelInstallDir/examples/camel-example-servlet-rest-blueprint

将 Servlet 组件配置为 REST 实现

camel-example-servlet-rest-blueprint 示例中,REST DSL 的底层实施由 Servlet 组件提供。Servlet 组件在 Blueprint XML 文件中配置,如 例 4.1 “为 REST DSL 配置 Servlet 组件” 所示。

例 4.1. 为 REST DSL 配置 Servlet 组件

<?xml version="1.0" encoding="UTF-8"?>
<blueprint ...>

  <!-- to setup camel servlet with OSGi HttpService -->
  <reference id="httpService" interface="org.osgi.service.http.HttpService"/>

  <bean class="org.apache.camel.component.servlet.osgi.OsgiServletRegisterer"
        init-method="register"
        destroy-method="unregister">
    <property name="alias" value="/camel-example-servlet-rest-blueprint/rest"/>
    <property name="httpService" ref="httpService"/>
    <property name="servlet" ref="camelServlet"/>
  </bean>

  <bean id="camelServlet" class="org.apache.camel.component.servlet.CamelHttpTransportServlet"/>
  ...
  <camelContext xmlns="http://camel.apache.org/schema/blueprint">

    <restConfiguration component="servlet"
                       bindingMode="json"
                       contextPath="/camel-example-servlet-rest-blueprint/rest"
                       port="8181">
      <dataFormatProperty key="prettyPrint" value="true"/>
    </restConfiguration>
    ...
  </camelContext>

</blueprint>

要使用 REST DSL 配置 Servlet 组件,您需要配置由以下三个层组成的堆栈:

REST DSL 层
REST DSL 层由 restConfiguration 元素配置,该元素通过将 component 属性设置为值 servlet 来与 Servlet 组件集成。
servlet 组件层
Servlet 组件层作为类的实例 CamelHttpTransportServlet 实施,其中示例实例具有 bean ID( camelServlet )。
HTTP 容器层

Servlet 组件必须部署到 HTTP 容器中。Karaf 容器通常配置有默认的 HTTP 容器(a Jetty HTTP 容器),它监听端口 8181 上的 HTTP 请求。要将 Servlet 组件部署到默认的 Jetty 容器,您需要执行以下操作:

  1. 获得对 org.osgi.service.http.HttpService compliant 服务(其中这个服务)是标准的 OSGi 接口,它提供了一个标准化的 OSGi 接口,提供对 OSGi 中默认 HTTP 服务器的访问。
  2. 创建 utility 类的实例 OsgiServletRegisterer,以在 HTTP 容器中注册 Servlet 组件。OsgiServletRegister 类是简化 Servlet 组件生命周期的实用程序。创建此类实例时,它会自动调用 HttpService OSGi 服务中的 registerServlet 方法;在实例被销毁时,它会自动调用 unregister 方法。

所需的依赖项

这个示例有两个依赖项,它们是 REST DSL 的关键重要,如下所示:

servlet 组件

提供 REST DSL 的底层实施。这在 Maven POM 文件中指定,如下所示:

<dependency>
  <groupId>org.apache.camel</groupId>
  <artifactId>camel-servlet</artifactId>
  <version>${camel-version}</version>
</dependency>

在将应用程序捆绑包部署到 OSGi 容器之前,您必须安装 Servlet 组件功能,如下所示:

JBossFuse:karaf@root> features:install camel-servlet
jackson 数据格式

提供 JSON 数据格式实施。这在 Maven POM 文件中指定,如下所示:

<dependency>
  <groupId>org.apache.camel</groupId>
  <artifactId>camel-jackson</artifactId>
  <version>${camel-version}</version>
</dependency>

在将应用程序捆绑包部署到 OSGi 容器之前,您必须安装 Jackson 数据格式功能,如下所示:

JBossFuse:karaf@root> features:install camel-jackson

Java 类型用于响应

示例应用程序会在 HTTP 请求和 Response 消息中回传递 User 类型对象。User Java 类定义为 例 4.2 “用于 JSON 响应的用户类” 所示。

例 4.2. 用于 JSON 响应的用户类

// Java
package org.apache.camel.example.rest;

public class User {

    private int id;
    private String name;

    public User() {
    }

    public User(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

User 类具有 JSON 数据格式相对简单表示。例如,此类的典型实例以 JSON 格式表示:

{
    "id" : 1234,
    "name" : "Jane Doe"
}

带有 JSON 绑定的 REST DSL 路由示例

本例中的 REST DSL 配置和 REST 服务定义显示在 例 4.3 “带有 JSON 绑定的 REST DSL 路由” 中。

例 4.3. 带有 JSON 绑定的 REST DSL 路由

<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           ...>
  ...
  <!-- a bean for user services -->
  <bean id="userService" class="org.apache.camel.example.rest.UserService"/>

  <camelContext xmlns="http://camel.apache.org/schema/blueprint">

    <restConfiguration component="servlet"
                       bindingMode="json"
                       contextPath="/camel-example-servlet-rest-blueprint/rest"
                       port="8181">
      <dataFormatProperty key="prettyPrint" value="true"/>
    </restConfiguration>

    <!-- defines the REST services using the  base path, /user -->
    <rest path="/user" consumes="application/json" produces="application/json">
      <description>User rest service</description>

      <!-- this is a rest GET to view a user with the given id -->
      <get uri="/{id}" outType="org.apache.camel.example.rest.User">
        <description>Find user by id</description>
        <to uri="bean:userService?method=getUser(${header.id})"/>
      </get>

      <!-- this is a rest PUT to create/update a user -->
      <put type="org.apache.camel.example.rest.User">
        <description>Updates or create a user</description>
        <to uri="bean:userService?method=updateUser"/>
      </put>

      <!-- this is a rest GET to find all users -->
      <get uri="/findAll" outType="org.apache.camel.example.rest.User[]">
        <description>Find all users</description>
        <to uri="bean:userService?method=listUsers"/>
      </get>

    </rest>

  </camelContext>

</blueprint>

REST 操作

例 4.3 “带有 JSON 绑定的 REST DSL 路由” 中的 REST 服务定义以下 REST 操作:

GET /camel-example-servlet-rest-blueprint/rest/user/{id}
获取 {id} 识别的用户的详细信息,其中以 JSON 格式返回 HTTP 响应。
PUT /camel-example-servlet-rest-blueprint/rest/user
创建新用户,其中用户详情包含在 PUT 消息正文中,采用 JSON 格式编码(与 User 对象类型匹配)。
GET /camel-example-servlet-rest-blueprint/rest/user/findAll
获取 所有用户 的详情,其中 HTTP 响应作为用户数组返回,格式为 JSON 格式。

调用 REST 服务的 URL

通过检查 例 4.3 “带有 JSON 绑定的 REST DSL 路由” 中的 REST DSL 定义,您可以将调用每个 REST 操作所需的 URL 组成。例如,要调用第一个 REST 操作,它会返回具有给定 ID 的用户详情,其 URL 会按如下方式构建:

http://localhost:8181
restConfiguration 中,协议默认为 http,端口明确设置为 8181
/camel-example-servlet-rest-blueprint/rest
restConfiguration 元素的 contextPath 属性指定。
/user
rest 元素的 path 属性指定。
/{id}
get verb 元素的 uri 属性指定。

因此,您可以在命令行中输入以下命令来使用 curl 实用程序调用此 REST 操作:

curl -X GET -H "Accept: application/json" http://localhost:8181/camel-example-servlet-rest-blueprint/rest/user/123

同样,可以通过 curl 调用剩余的 REST 操作,输入以下示例命令:

curl -X GET -H "Accept: application/json" http://localhost:8181/camel-example-servlet-rest-blueprint/rest/user/findAll

curl -X PUT -d "{ \"id\": 666, \"name\": \"The devil\"}" -H "Accept: application/json" http://localhost:8181/camel-example-servlet-rest-blueprint/rest/user