4.3. 到 Java 对象和从 Java 对象进行复制
用于通过 HTTP 传输的 Java 对象
使用 REST 协议的最常见方法是传输消息正文中的 Java Bean 的内容。为了实现此目的,您需要有一个机制来聚合 Java 对象以及适当的数据格式。REST DSL 支持以下数据格式(适合编码 Java 对象):
- JSON
JSON (JavaScript 对象表示法)是一个轻量级数据格式,可轻松映射到 Java 对象或从 Java 对象映射。JSON 语法是紧凑的,易于输入,易于读和写。出于所有这些原因,JSON 已经成为 REST 服务的消息格式。
例如,以下 JSON 代码可以代表具有两个属性字段
id
和name
的User
bean:{ "id" : 1234, "name" : "Jane Doe" }
- JAXB
JAXB (适用于 XML 绑定的 Java 架构)是基于 XML 的数据格式,可轻松映射到 Java 对象或从 Java 对象映射。要将 XML 汇集到 Java 对象,您还必须注解要使用的 Java 类。
例如,以下 JAXB 代码可以代表具有两个属性字段
id
和name
的User
bean:<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <User> <Id>1234</Id> <Name>Jane Doe</Name> </User>
注意从 Camel 2.17.0,JAXB 数据格式和类型转换器支持从 XML 转换到 POJO,即使用
ObjectFactory
而不是XmlRootElement
。另外,camel 上下文应包含CamelJaxbObjectFactory
属性,值为 true。但是,由于优化,默认值为 false。
JSON 和 JAXB 与 REST DSL 集成
当然,您可以编写所需的代码,以自己将消息正文转换为 Java 对象或从 Java 对象转换。但 REST DSL 提供了自动执行此转换的便利。特别是,将 JSON 和 JAXB 与 REST DSL 集成具有以下优点:
- 自动对 Java 对象和从 Java 对象进行 Marshalling (因为适当的配置)。
- REST DSL 可以自动检测数据格式(JSON 或 JAXB),并执行适当的转换。
- REST DSL 提供了一个抽象层,因此您编写的代码不特定于特定的 JSON 或 JAXB 实施。因此,您可以稍后切换实施,对应用程序代码的影响最小。
支持的数据格式组件
Apache Camel 提供了 JSON 和 JAXB 数据格式的多种不同的实现。REST DSL 目前支持以下数据格式:
JSON
-
jackson 数据格式(
camel-jackson
) (默认) -
gson 数据格式(
camel-gson
) -
xstream 数据格式(
camel-xstream
)
-
jackson 数据格式(
JAXB
-
JAXB 数据格式(
camel-jaxb
)
-
JAXB 数据格式(
如何启用对象 marshalling
要在 REST DSL 中启用对象整理,请观察以下点:
-
启用绑定模式,通过设置
bindingMode
选项(您可以在多个级别中,您可以设置绑定模式 swig-wagon 以获得详细信息,请参阅 “配置绑定模式”一节)。 -
使用 type 选项(必需)在传入消息中指定要转换为(或 from)的 Java
类型
(可选),在传出消息中使用outType
选项(可选)。 - 如果要将 Java 对象转换为 JAXB 数据格式,您必须记得使用适当的 JAXB 注释给 Java 类添加注解。
-
使用
jsonDataFormat
选项和/或xmlDataFormat
选项(可以在restConfiguration
构建器中指定)指定底层数据格式实现(或实现)。 如果您的路由以 JAXB 格式提供返回值,您通常要将交换正文的 Out 消息设置为带有 JAXB 注释( JAXB 元素)的类实例。但是,如果您想以 XML 格式直接提供 JAXB 返回值,请将
dataFormatProperty
设置为 keyxml.out.mustBeJAXBElement
,它可在restConfiguration
构建器上指定。例如,在 XML DSL 语法中:
<restConfiguration ...> <dataFormatProperty key="xml.out.mustBeJAXBElement" value="false"/> ... </restConfiguration>
将所需的依赖项添加到项目构建文件中。例如,如果您使用 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>
将应用程序部署到 OSGi 容器时,请记住为您选择的数据格式安装必要的功能。例如,如果您使用 Jackson 数据格式(默认),您可以通过输入以下 Karaf console 命令安装
camel-jackson
功能:JBossFuse:karaf@root> features:install camel-jackson
或者,如果您正在部署到 Fabric 环境中,您可以将该功能添加到 Fabric 配置文件中。例如,如果您使用配置集
MyRestProfile
,您可以输入以下 console 命令来添加功能:JBossFuse:karaf@root> fabric:profile-edit --features camel-jackson MyRestProfile
配置绑定模式
bindingMode
选项默认为 off
,因此您必须明确配置它,以便启用 Java 对象的 marshalling。TABLE 显示支持的绑定模式列表。
从 Camel 2.16.3 开始,只有在 content-type 标头包含 json 或 xml 时才会发生从 POJO 到 JSon/JAXB 的绑定。如果消息正文不应该尝试使用绑定进行 marshalled,则这允许您指定自定义 content-type。例如,当消息正文是自定义二进制有效负载时,这很有用。
绑定模式 | 描述 |
---|---|
| 绑定关闭 (默认)。 |
| 为 JSON 和/或 XML 启用绑定。在此模式中,Camel 根据传入消息的格式自动选择 JSON 或 XML (JAXB)。您不需要 启用两种类型的数据格式,但:一个 JSON 实现、XML 实现或两者都可通过 classpath 提供。 |
|
仅为 JSON 启用绑定。必须在 classpath 上提供 JSON 实现(默认情况下,Camel 会尝试启用 |
|
仅为 XML 启用绑定。必须在 classpath 上提供 XML 实施(默认情况下,Camel 会尝试启用 |
| 为 JSON 和 XML 都启用绑定。在此模式中,Camel 根据传入消息的格式自动选择 JSON 或 XML (JAXB)。您需要在 classpath 上提供两种类型的数据格式。 |
在 Java 中,这些绑定模式值表示为以下 enum
类型的实例:
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("...");
Example
如需完整的代码示例,显示如何使用 REST DSL (将 Servlet 组件用作 REST 实施),请查看 Apache Camel camel-example-servlet-rest-blueprint
示例。您可以通过安装独立 Apache Camel 分发 apache-camel-2.23.2.fuse-7_13_0-00013-redhat-00001.zip
来查找此示例,该版本在 Fuse 安装的 extras/
子目录中提供。
安装独立 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 IDcamelServlet
。 - HTTP 容器层
Servlet 组件必须部署到 HTTP 容器中。Karaf 容器通常配置有默认 HTTP 容器(Jetty HTTP 容器),它监听端口 8181 上的 HTTP 请求。要将 Servlet 组件部署到默认的 Jetty 容器,您需要执行以下操作:
-
获得
org.osgi.service.http.HttpService
OSGi 服务的 OSGi 参考,此服务是标准的 OSGi 接口,可在 OSGi 中提供对默认 HTTP 服务器的访问权限。 -
创建 utility 类(
OsgiServletRegisterer
)的实例,以在 HTTP 容器中注册 Servlet 组件。OsgiServletRegisterer
类是一个简化管理 Servlet 组件的生命周期的工具。创建此类实例时,它会自动调用HttpService
OSGi 服务上的registerServlet
方法;当实例被销毁时,它会自动调用未注册的方法。
-
获得
所需的依赖项
这个示例有两个依赖项,它们对 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
- Jacks data format
提供 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 类型
example 应用在 HTTP Request 和 Response 消息中返回 User
type 对象。用户
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