HTTP 请求和响应是基于文本的,意味着浏览器和服务器通过交换原始文本进行通信。但是,使用 Spring,controller 类中的方法返回纯 'String' 类型和域模型(或其他 Java 内建对象)。如何将对象序列化/反序列化为原始文本?这由
HttpMessageConverter
处理。Spring 具有捆绑实现,可满足常见需求。表 1 显示了一些示例。
表 1. HttpMessageConverter 示例
使用...... | 您可以...... |
---|---|
StringHttpMessageConverter | 从请求和响应读取/编写字符串。默认情况下,它支持媒体类型 text/* 并使用文本/无格式内容类型编写。 |
FormHttpMessageConverter | 从请求和响应读取/编写表单数据。默认情况下,它读取媒体类型 application/x-www-form-urlencoded 并将数据写入 MultiValueMap<String,String>。 |
MarshallingHttpMessageConverter | 使用 Spring 的 marshaller/un-marshaller 读取/编写 XML 数据。它转换媒体类型为 application/xml 的数据。 |
MappingJacksonHttpMessageConverter | 使用 Jackson 的 ObjectMapper 读取/编写 JSON 数据。它转换媒体类型为 application/json 的数据。 |
AtomFeedHttpMessageConverter | 使用 ROME 的 Feed API 读取/编写 ATOM 源。它转换媒体类型为 application/atom+xml 的数据。 |
RssChannelHttpMessageConverter | 使用 ROME 的 feed API 读取/编写 RSS 源。它转换媒体类型为 application/rss+xml 的数据。 |
以JSON为例,使用步骤如下:
清单 1. 配置 rest-servlet.xml 中的 HttpMessageConverter
<bean class="org.springframework.web.servlet.mvc.annotation
.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="jsonConverter" />
<ref bean="marshallingConverter" />
<ref bean="atomConverter" />
</list>
</property>
</bean>
<bean id="jsonConverter"
class="org.springframework.http.converter.json
.MappingJacksonHttpMessageConverter">
<property name="supportedMediaTypes" value="application/json" />
</bean>
在配置中,注册了 3 个转换程序。
MappingJacksonHttpMessageConverter
用于将对象转换为 JSON,反之亦然。此内置转换程序使用 Jackson 的 ObjectMapper
将 JSON 映射到 JavaBean,因此您必须将下列 Jackson JAR 文件添加到类路径。
-
org.codehaus.jackson.jar
-
org.codehaus.jackson.mapper.jar
下一步是编写一个方法,处理请求 JSON 具象的请求。清单 2 显示了详细信息。
清单 2. 处理在 EmployeeController 中定义的 JSON 请求
@RequestMapping(method=RequestMethod.GET, value="/emp/{id}",
headers="Accept=application/json")
public @ResponseBody Employee getEmp(@PathVariable String id) {
Employee e = employeeDS.get(Long.parseLong(id));
return e;
}
@RequestMapping(method=RequestMethod.GET, value="/emps",
headers="Accept=application/json")
public @ResponseBody EmployeeListinggetAllEmp() {
List<Employee> employees = employeeDS.getAll();
EmployeeListinglist = new EmployeeList(employees);
return list;
}
@ResponseBody
注释用于将返回对象(Employee
或 EmployeeList
)变为响应的正文内容,将使用 MappingJacksonHttpMessageConverter
将其映射到 JSON。
使用
HttpMessageConverter
和 @ResponseBody
,您可以实现多个具象,而无需包含 Spring 的视图技术 — 这是使用ContentNegotiatingViewResolver
所不具有的一个优势。
现在您可以使用 CURL 或 REST Client Firefox 插件调用请求。记住添加一个 HTTP 头:
Accept=application/json
。清单 3 以 JSON 格式显示了所需的响应。
清单 3. getEmp() 和 getAllEmp() 的 JSON 结果
Response for /rest/service/emp/1
{"id":1,"name":"Huang Yi Ming","email":"huangyim@cn.ibm.com"}
Response for /rest/service/emps
{"count":2,
"employees":[
{"id":1,"name":"Huang Yi Ming","email":"huangyim@cn.ibm.com"},
{"id":2,"name":"Wu Dong Fei","email":"wudongf@cn.ibm.com"}
]}
当然,也可以自定义转换器。自定义的话,通过继承 AbstractHttpMessageConverter类实现对应的方法。
配置自定义转换器:
<
mvc:annotation-driven
>
<
mvc:message-converters
register-defaults
=
"true"
>
<!-- 将StringHttpMessageConverter的默认编码设为UTF-8. -->
<
bean
class
=
"org.springframework.http.converter.StringHttpMessageConverter"
>
<
constructor-arg
value
=
"UTF-8"
/>
</
bean
>
<
bean
class
=
"com.*.MyselfHttpMessageConverter"
>
</
bean
>
</
mvc:message-converters
>
</
mvc:annotation-driven
>