4.3. 从 Java 对象提取至和进行 marshalling
marshalling Java 对象用于通过 HTTP 传输
使用 REST 协议的一个最常见方式是在消息正文中传输 Java bean 的内容。要实现此目的,您需要提供一种机制来将 Java 对象聚合到合适的数据格式中。REST DSL 支持下列数据格式,适用于编码 Java 对象:
- JSON
JSON (JavaScript 对象表示法)是一种轻量级数据格式,可轻松映射到 Java 对象或从 Java 对象映射。JSON 语法紧凑,更轻易输入,便于人类读取和写入。由于所有这些原因,JSON 已成为 REST 服务的消息格式。
例如,以下 JSON 代码可以代表一个
User
bean,其中有两个属性字段id
和name
:{ "id" : 1234, "name" : "Jane Doe" }
- JAXB
JAXB (用于 XML 绑定的 Java 架构)是一个基于 XML 的数据格式,可轻松映射到 Java 对象和 Java 对象。要将 XML 整理到 Java 对象,还必须注解您要使用的 Java 类。
例如,以下 JAXB 代码可以代表一个
User
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,JAXB 数据格式和类型转换器支持从 XML 转换到 POJO,用于使用
ObjectFactory
而不是XmlRootElement
的类。另外,camel 上下文应包含CamelJaxbObjectFactory
属性,值为 true。但是,由于优化了默认值是 false。
将 JSON 和 JAXB 与 REST DSL 集成
当然,您可以编写必要的代码,以自己将消息正文转换为和从 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 中启用对象 marshalling,请观察以下几点:
-
启用绑定模式,通过设置
bindingMode
选项(有多个级别,您可以在其中设置绑定模式)确保详情请查看 “配置绑定模式”一节。 -
指定要转换为(或从)传入消息的 Java 类型,使用
type
选项(必需),并在传出消息中带有outType
选项(可选)。 - 如果要将 Java 对象转换为 JAXB 数据格式或从 JAXB 数据格式转换,您必须记得使用适当的 JAXB 注释给 Java 类添加注解。
-
使用
jsonDataFormat
选项和/或xmlDataFormat
选项(可以在restConfiguration
构建器中指定),指定底层数据格式实现(或实现)。 如果您的路由以 JAXB 格式提供返回值,您通常应当将交换正文的 Out 消息设置为含有 JAXB 注解的类实例(一个 JAXB 元素)。如果您希望直接以 XML 格式提供 JAXB 返回值,但是,使用键
xml.out.mustBeJAXBElement
设置为false
(可以在restConfiguration
构建器上指定)的dataFormatProperty
。例如,在 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 控制台来安装
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 显示支持的绑定模式列表。
从 Camel 2.16.3 开始,仅当 content-type 标头包含 json 或 xml 时,从 POJO 到 JSon/JAXB 的绑定才会发生。这可让您在消息正文没有使用绑定时指定自定义 content-type。这很有用,例如,消息正文是一个自定义二进制有效负载。
绑定模式 | 描述 |
---|---|
| 关闭 (默认)绑定。 |
| 为 JSON 和/或 XML 启用绑定。在这个模式中,Camel auto-selects JSON 或 XML (JAXB)基于传入消息的格式。您不需要 同时启用多种数据格式,但:JSON 实施、XML 实施或两者都可以在类路径上提供。 |
|
仅针对 JSON 启用绑定。必须在 类路径上提供 JSON 实施(默认情况下,Camel 会尝试启用 |
|
仅为 XML 启用绑定。必须在 类路径上提供 XML 实施(默认情况下,Camel 会尝试启用 |
| 为 JSON 和 XML 启用绑定。在这个模式中,Camel auto-selects JSON 或 XML (JAXB)基于传入消息的格式。您需要在类路径上提供两种数据格式。 |
在 Java 中,这些绑定模式值表示为以下枚举的实例:
org.apache.camel.model.rest.RestBindingMode
您可以在其中设置 绑定Mode
有几个不同级别,如下所示:
- 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-790054-redhat-00001.zip
,该示例在 Fuse 安装的额外 /
子目录中提供。
安装独立 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 容器(a Jetty HTTP 容器)配置,该容器监听端口 8181 上的 HTTP 请求。要将 Servlet 组件部署到默认的 Jetty 容器,您需要执行以下操作:
-
获取 OSGi 参考
org.osgi.service.http.HttpService
OSGi 服务,其中该服务是标准的 OSGi 接口,提供对 OSGi 中默认 HTTP 服务器的访问。 -
创建 utility 类
OsgiServletRegister
的实例,以在 HTTP 容器中注册 Servlet 组件。OsgiServletRegister
类是一个实用程序,可以简化 Servlet 组件的生命周期。创建此类的实例时,它会自动调用HttpService
OSGi 服务的registerServlet
方法;当实例销毁时,它会自动调用unregister
方法。
-
获取 OSGi 参考
所需的依赖项
这个示例有两个与 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 请求和响应消息中返回。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 定义,您可以将所需的 URL 组合在一起,以调用每个 REST 操作。例如,要调用第一个 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