4.3. 摘要到 Java 对象以及
用于通过 HTTP 传输的 Java 对象
使用 REST 协议的最常见方式之一是传输消息正文中 Java Bean 的内容。为了实现此工作,您需要有一个机制来汇总 Java 对象,以及从适当的数据格式放入其中。REST DSL 支持下列数据格式适用于编码 Java 对象:
- JSON
JSON (JavaScript 对象表示法)是一个轻量级数据格式,可轻松从 Java 对象映射。JSON 语法是紧凑、轻便键入的,方便人进行读和写。因此,JSON 已成为 REST 服务的消息格式。
例如,以下 JSON 代码可以代表用户 bean,具有两个属性字段,即
id
和name
:{ "id" : 1234, "name" : "Jane Doe" }
- JAXB
JAXB (XML Binding 的 Java 架构)是基于 XML 的数据格式,可轻松映射到 Java 对象或从 Java 对象映射。要将 XML 接合到 Java 对象,还必须注解您要使用的 Java 类。
例如,以下 JAXB 代码可以代表用户 bean,其中有两个属性字段:
id
和name
:<?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
)
-
jackson 数据格式(
JAXB
-
JAXB 数据格式(
camel-jaxb
)
-
JAXB 数据格式(
如何启用对象 marshalling
要在 REST DSL 中启用对象摘要,请观察以下几点:
-
启用绑定模式,通过设置
bindingMode
选项(有几个级别可设置绑定模式)。如需详情,请参阅 “配置绑定模式”一节。 -
使用
type
选项(必需)以及带有outType
选项(可选)的传出消息上指定要转换为的 Java 类型(或从中)。 - 如果要将 Java 对象转换为 JAXB 数据格式,您必须记得使用适当的 JAXB 注释给 Java 类添加注解。
-
指定底层数据格式实现(或实现),使用
jsonDataFormat
选项和/或xmlDataFormat
选项(可以在restConfiguration
构建器中指定)。 如果您的路由以 JAXB 格式提供返回值,则通常您希望将交换正文的 Out 消息设置为带有 JAXB 注释(a JAXB 元素)的类实例。如果您希望以 XML 格式直接提供 JAXB 返回值,但是,使用键
xml.out.mustBeJAXBElement
将dataFormatProperty
设置为false
(可以在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 数据格式(默认),则通过输入以下命令来安装
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 标头包含 json 或 xml 的绑定时,从 POJO 到 JSon/JAXB 的绑定才会进行 Camel 2.16.3。如果消息正文不应尝试使用绑定进行总结,这允许您指定自定义内容类型。例如,当消息正文是一个自定义二进制有效负载时,这很有用。
绑定模式 | 描述 |
---|---|
| 关闭绑定 (默认)。 |
| 为 JSON 和/或 XML 启用绑定。在这个模式中,Camel 会自动根据传入消息的格式自动选择 JSON 或 XML(JAXB)。您不需要 同时启用两种数据格式:JSON 实现、XML 实现,或两者都可以在类路径中提供。 |
|
仅为 JSON 启用了绑定。必须在 classpath 上提供 JSON 实施(默认为 Camel 尝试启用 |
|
仅为 XML 启用绑定。必须在 classpath 上提供一个 XML 实现(默认为 Camel 尝试启用 |
| 为 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 容器,您需要执行以下操作:
-
获得对
org.osgi.service.http.HttpService
compliant 服务(其中这个服务)是标准的 OSGi 接口,它提供了一个标准化的 OSGi 接口,提供对 OSGi 中默认 HTTP 服务器的访问。 -
创建 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