Spring,构建 Java™ 平台和 Enterprise Edition (Java EE) 应用程序的著名框架,现在在其模型-视图-控制器(Model-View-Controller ,MVC)层支持具象状态传输 (REST)。RESTful web 服务根据客户端请求生成多个具象(representations)很重要。在本篇文章中,学习使用HttpMessageConverter
生成多个具象。代码示例展示如何使用 RestTemplate
和HttpMessageConverter
与服务进行通信。此外,还将学习如何使用 Spring API 和注释构建 RESTful web 服务,生成常见具象,比如 ATOM Feed、XML 和 JavaScript Object Notation (JSON)。
简介
随附文章,“使用 Spring 3 构建 RESTful web 服务”(参见 参考资料),介绍了使用 Spring 构建 RESTful web 服务的方式。还解释了如何使用ContentNegotiatingViewResolver
生成多个具象,这是 RESTful web 服务的一个重要功能。本文还阐述了使用 HttpMessageConverter
生成多个具象的另一种方式,并且本文中的示例展示了如何使用 RestTemplate
和 HttpMessageConverter
与服务进行通信。
Spring MVC 中的 REST 支持
本部分提供了支持 RESTful web 服务的主要 Spring 功能(或注释)的概述。
@Controller
@Controller
注释对将成为 MVC 中控制器的类进行注释并处理 HTTP 请求。@RequestMapping
@RequestMapping
注释对函数进行注释,该函数处理某些 HTTP 方法、URI 或 HTTP 头。此注释是 Spring REST 支持的关键。可以更改method
参数以处理其他 HTTP 方法。
例如:
@RequestMapping(method=RequestMethod.GET, value="/emps",
headers="Accept=application/xml, application/json")
@PathVariable
使用 @PathVariable
注释可将 URI 中的路径变量作为参数插入。
例如:
@RequestMapping(method=RequestMethod.GET, value="/emp/{id}") public ModelAndView getEmployee(@PathVariable String id) { … }
其他有用的注释
使用 @RequestParam
将 URL 参数插入方法中。
使用 @RequestHeader
将某一 HTTP 头插入方法中。
使用 @RequestBody
将 HTTP 请求正文插入方法中。
使用 @ResponseBody
将内容或对象作为 HTTP 响应正文返回。
使用 HttpEntity<T>
将它自动插入方法中,如果将它作为参数提供。
使用 ResponseEntity<T>
返回具有自定义状态或头的 HTTP 响应。
例如:
public @ResponseBody Employee getEmployeeBy(@RequestParam("name") String name, @RequestHeader("Accept") String accept, @RequestBody String body) {…} public ResponseEntity<String> method(HttpEntity<String> entity) {…}
参见 Spring 文档(参见 参考资料) 获得可插入方法中的支持注释或对象的完整列表。
多具象支持
使用不同 MIME 类型表示同一资源是 RESTful web 服务的一个重要方面。通常,可以使用具有不同 "accept" HTTP 头的同一 URI 提取具有不同表示的资源。还可以使用不同的 URI 或具有不同请求参数的 URI。
“使用 Spring 3 构建 RESTful web 服务”(参见 参考资料)介绍了
ContentNegotiatingViewResolver
,可以挑选不同的视图解析器处理同一 URI(具有不同的 accept 头)。因此,ContentNegotiatingViewResolver
可用于生成多个具象。
还有另一种方式可生成多具象 — 将
HttpMessageConverter
和 c@ResponseBody
注释结合起来使用。使用这种方法无需使用视图技术。
HttpMessageConverter
HTTP 请求和响应是基于文本的,意味着浏览器和服务器通过交换原始文本进行通信。但是,使用 Spring,controller 类中的方法返回纯 'String' 类型和域模型(或其他 Java 内建对象)。如何将对象序列化/反序列化为原始文本?这由
HttpMessageConverter
处理。Spring 具有捆绑实现,可满足常见需求。表 1 显示了一些示例。
表 1. HttpMessageConverter 示例
从请求和响应读取/编写字符串。默认情况下,它支持媒体类型 text/* 并使用文本/无格式内容类型编写。 |
从请求和响应读取/编写表单数据。默认情况下,它读取媒体类型 application/x-www-form-urlencoded 并将数据写入 MultiValueMap<String,String>。 |
使用 Spring 的 marshaller/un-marshaller 读取/编写 XML 数据。它转换媒体类型为 application/xml 的数据。 |
使用 Jackson 的 ObjectMapper 读取/编写 JSON 数据。它转换媒体类型为 application/json 的数据。 |
使用 ROME 的 Feed API 读取/编写 ATOM 源。它转换媒体类型为 application/atom+xml 的数据。 |
使用 ROME 的 feed API 读取/编写 RSS 源。它转换媒体类型为 application/rss+xml 的数据。 |
构建 RESTful web 服务
在此部分中,学习构建可生成多个具象的简单 RESTful web 服务。示例应用程序中使用的一些资源在 “使用 Spring 3 构建 RESTful web 服务”(参见 参考资料)中构建。还可以 下载 示例代码。
首先,您必须配置
HttpMessageConverter
。要生成多个具象,自定义几个 HttpMessageConverter
实例,以将对象转换为不同的媒体类型。此部分包括 JSON、ATOM 和 XML 媒体类型。
JSON
从最简单的示例开始。JSON 是一个轻量型的数据交换格式,人们可轻松地进行读取和编写。清单 1 显示了配置 JSON converter 的代码。
清单 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"}
]}
XML
Spring 的内置转换程序
MarshallingHttpMessageConverter
用于在对象和 XML (OXM) 之间进行映射。本示例使用 JAXB 2 作为转换程序的 marshaller/un-marshaller。清单 4 显示了配置。
清单 4. 配置 MarshallingHttpMessageConverter
<bean id="marshallingConverter"
class="org.springframework.http.converter.xml
.MarshallingHttpMessageConverter">
<constructor-arg ref="jaxbMarshaller" />
<property name="supportedMediaTypes" value="application/xml"/>
</bean>
<bean id="jaxbMarshaller"
class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="classesToBeBound">
<list>
<value>dw.spring3.rest.bean.Employee</value>
<value>dw.spring3.rest.bean.EmployeeList</value>
</list>
</property>
</bean>
了解 JAXB 2 不能很好地支持 java.util.List<T> 到 XML 的映射很重要。常用实践是为对象集添加一个包装类。参见 “使用 Spring 3 构建 RESTful web 服务”(参见 参考资料)或 下载 源代码,了解此 JAXB 注释类的详细信息。
在处理请求的控制器中的方法如何?回顾一下 清单 2 中的代码。发现在此处不需要添加任何代码一点也不奇怪。您只需要在
Accept
头中添加另一个支持的媒体类型,如下所示。
headers=”Accept=application/json, application/xml”
转换程序将对象正确地映射到请求的类型(JSON 或 XML)。清单 5 显示了请求 application/xml 具象的理想结果。
清单 5. getEmp() 和 getAllEmp() 的 XML 结果
Response for /rest/service/emp/1
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<employee>
<email>huangyim@cn.ibm.com</email>
<id>1</id>
<name>Huang Yi Ming</name>
</employee>
Response for /rest/service/emps
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<employees>
<count>2</count>
<employee>
<email>huangyim@cn.ibm.com</email>
<id>1</id>
<name>Huang Yi Ming</name>
</employee>
<employee>
<email>wudongf@cn.ibm.com</email>
<id>2</id><name>Wu Dong Fei</name>
</employee>
</employees>
ATOM 源
ATOM 源是另一种在 RESTful web 服务中交换数据的常见格式。Atom 源文档是 Atom 源(包括有关源及与其相关的所有或部分项的元数据)的具象。其根是
atom:feed
元素。还有一个 ATOM Publish Protocol (APP) 定义交换格式和行为。(定义 ATOM 和 APP 格式不在本文的讨论范围内。参见 参考资料 了解更多信息。)
本示例使用
AtomFeedHttpMessageConverter
转换 ATOM 源,利用 ROME ATOM API。因此,您必须在类路径中包含 JAR 文件 sun.syndication.jar。清单 6 显示了此转换程序的配置。
清单 6. 配置 AtomFeedHttpMessageConverter
<bean id="atomConverter"
class="org.springframework.http.converter.feed
.AtomFeedHttpMessageConverter">
<property name="supportedMediaTypes" value="application/atom+xml" />
</bean>
清单 7 显示了处理 ATOM 请求和源生成的代码。
清单 7. EmployeeController & AtomUtil 类中的 getEmpFeed()
@RequestMapping(method=RequestMethod.GET, value="/emps",
headers="Accept=application/atom+xml")
public @ResponseBody Feed getEmpFeed() {
List<Employee> employees = employeeDS.getAll();
return AtomUtil.employeeFeed(employees, jaxb2Mashaller);
}
public static Feed employeeFeed(
List<Employee> employees, Jaxb2Marshaller marshaller) {
Feed feed = new Feed();
feed.setFeedType("atom_1.0");
feed.setTitle("Employee Atom Feed");
List<Entry> entries = new ArrayList<Entry>();
for(Employee e : employees) {
StreamResult result = new StreamResult(
new ByteArrayOutputStream());
marshaller.marshal(e, result);
String xml = result.getOutputStream().toString();
Entry entry = new Entry();
entry.setId(Long.valueOf(e.getId()).toString());
entry.setTitle(e.getName());
Content content = new Content();
content.setType(Content.XML);
content.setValue(xml);
List<Content> contents = new ArrayList<Content>();
contents.add(content);
entry.setContents(contents);
entries.add(entry);
}
feed.setEntries(entries);
return feed;
}
在上述代码中,注意:
getEmpFeed()
方法将同一 URI 处理为getAllEmp()
,但具有不同的Accept
头。使用
employeeFeed()
方法,您可以将Employee
对象解析为 XML,然后将其添加到源项的<content>
元素。
清单 8 显示了请求 URI /rest/service/emps 的 application/atom+xml 具象时的输出。
清单 8. 请求 application/atom+xml 时的 /rest/service/emps 输出
<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Employee Atom Feed</title>
<entry>
<title>Huang Yi Ming</title>
<id>1</id>
<content type="xml">
<employee>
<email>huangyim@cn.ibm.com</email>
<id>1</id>
<name>Huang Yi Ming</name>
</employee>
</content>
</entry>
<entry>
<title>Wu Dong Fei</title>
<id>2</id>
<content type="xml">
<employee>
<email>wudongf@cn.ibm.com</email>
<id>2</id>
<name>Wu Dong Fei</name>
</employee>
</content>
</entry>
</feed>
实现 POST、PUT 和 DELETE
目前为止,示例已实现了几个处理 HTTP
GET
方法的方法。清单 9 显示了 POST
、PUT
和 DELETE
方法的实现。
清单 9. EmployeeController 中的 POST、PUT 和 DELETE 方法
@RequestMapping(method=RequestMethod.POST, value="/emp")
public @ResponseBody Employee addEmp(@RequestBody Employee e) {
employeeDS.add(e);
return e;
}
@RequestMapping(method=RequestMethod.PUT, value="/emp/{id}")
public @ResponseBody Employee updateEmp(
@RequestBody Employee e, @PathVariable String id) {
employeeDS.update(e);
return e;
}
@RequestMapping(method=RequestMethod.DELETE, value="/emp/{id}")
public @ResponseBody void removeEmp(@PathVariable String id) {
employeeDS.remove(Long.parseLong(id));
}
@RequestBody
注释在 addEmp()
和 updateEmp()
方法中使用。它接收 HTTP 请求正文并试图使用注册的 HttpMessageConverter
将其转换为对象类。在下一部分中,您将使用 RestTemplate
与这些服务进行通信。
使用 RestTemplate 与 REST 服务进行通信
“使用 Spring 3 构建 RESTful web 服务”(参见 参考资料)介绍了如何使用 CURL 和 REST 客户端测试 REST 服务。从编程水平上讲,Jakarta Commons HttpClient 通常用于完成此测试(但这不在本文的讨论范围中)。您还可以使用名为
RestTemplate
的 Spring REST 客户端。从概念上讲,它与 Spring 中的其他模板类相似,比如 JdbcTemplate
和 JmsTemplate
。
RestTemplate
还使用 HttpMessageConverter
。您可以将对象类传入请求并使转换程序处理映射。
配置 RestTemplate
清单 10 显示了
RestTemplate
的配置。它还使用之前介绍的 3 个转换程序。
清单 10. 配置 RestTemplate
<bean id="restTemplate"
class="org.springframework.web.client.RestTemplate">
<property name="messageConverters">
<list>
<ref bean="marshallingConverter" />
<ref bean="atomConverter" />
<ref bean="jsonConverter" />
</list>
</property>
</bean>
本文中的示例仅使用了一些可简化服务器之间通信的方法。
RestTemplate
支持其他方法,包括:
exchange
:使用请求正文执行一些 HTTP 方法并获得响应。getForObject
:执行 HTTPGET
方法并将响应作为对象获得。postForObject
:使用特定请求正文执行 HTTPPOST
方法。put
:使用特定请求正文执行 HTTPPUT
方法。delete
:执行 HTTPDELETE
方法以获得特定 URI。
代码示例
下列代码示例帮助阐述如何使用
RestTemplate
。参见 RestTemplate API(参见 参考资料)获得使用的 API 的详细说明。
清单 11 显示如何将头添加到请求中,然后调用请求。使用
MarshallingHttpMessageConverter
您可以获得响应并将其转换为类型类。可以使用不同的媒体类型测试其他具象。
清单 11. XML 具象请求
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_XML);
HttpEntity<String> entity = new HttpEntity<String>(headers);
ResponseEntity<EmployeeList> response = restTemplate.exchange(
"http://localhost:8080/rest/service/emps",
HttpMethod.GET, entity, EmployeeList.class);
EmployeeListingemployees = response.getBody();
// handle the employees
清单 12 显示了如何将新员工发布到服务器。服务器端服务
addEmp()
可接受媒体类型为 application/xml 和 application/json 的数据。
清单 12. 发布新员工
Employee newEmp = new Employee(99, "guest", "guest@ibm.com");
HttpEntity<Employee> entity = new HttpEntity<Employee>(newEmp);
ResponseEntity<Employee> response = restTemplate.postForEntity(
"http://localhost:8080/rest/service/emp", entity, Employee.class);
Employee e = response.getBody();
// handle the employee
清单 13 显示了如何 PUT 修改的员工以更新旧员工。它还显示了可用作请求 URI 占位符(
{id}
)的功能。
清单 13. PUT 以更新员工
Employee newEmp = new Employee(99, "guest99", "guest99@ibm.com");
HttpEntity<Employee> entity = new HttpEntity<Employee>(newEmp);
restTemplate.put(
"http://localhost:8080/rest/service/emp/{id}", entity, "99");
清单 14 显示了如何 DELETE 现有员工。
清单 14. DELETE 现有员工
restTemplate.delete(
"http://localhost:8080/rest/service/emp/{id}", "99");
结束语
在本篇文章中,您学习了 Spring 3 中引入的
HttpMessageConverter
。它提供了对多具象的客户端和服务器端支持。使用提供的 源代码,您可以探索本文中的 HttpMessageConverter
实现和使用 “使用 Spring 3 构建 RESTful web 服务” 中的 ContentNegotiatingViewResolver
实现之间的差异。
http://www.ibm.com/developerworks/cn/web/wa-restful/
相关推荐
在开发 RESTful Web 服务时,Spring MVC 的 HttpMessageConverter 是一个至关重要的组件。这个功能允许我们将 Java 对象转换为 HTTP 响应消息,并将 HTTP 请求消息解析为 Java 对象。本文将深入探讨如何利用 Spring ...
描述中的“spring4 mvc restful web json”进一步强调了在Spring 4 MVC上下文中使用RESTful Web服务和JSON数据格式。Spring MVC是Spring框架的一部分,用于构建Web应用程序。通过RESTful设计,我们可以创建资源导向...
13. **RESTful 风格**:Spring MVC 可以很方便地支持 RESTful 风格的 Web 服务,利用 HTTP 方法(GET、POST、PUT、DELETE 等)来操作资源。 14. **模板引擎**:Spring MVC 可以与多种模板引擎集成,如 Thymeleaf,...
综上所述,使用Spring构建RESTful API涉及到从初始配置到具体接口实现的多个步骤,包括Web应用的初始化、REST API的构建、数据转换、异常处理等方面。通过这些技术,开发者可以构建出高效、灵活且易于扩展的API服务...
《Spring Web MVC 3.1.1.RELEASE:构建高效Web应用的核心技术解析》 Spring Web MVC是Spring框架的重要组成部分,专为构建基于Java的Web应用程序而设计。它提供了模型-视图-控制器(MVC)架构模式的实现,允许...
2. **Improved REST Support**:Spring 3.1增强了对RESTful Web服务的支持,通过新增的@PathVariable、@MatrixVariable、@RequestParam和@RequestHeader等注解,使得参数绑定更加灵活,更方便地处理HTTP请求的不同...
Spring MVC 是一个基于 Java 的轻量级 Web 开发框架,它是 Spring 框架的一部分,主要用于构建 MVC(Model-View-Controller)模式的 Web 应用程序。在现代 Web 开发中,JSON(JavaScript Object Notation)作为一种...
总的来说,Spring4.3.7的Web整合包是一个全面的解决方案,涵盖了Web开发中的许多方面,包括MVC、WebSocket、RESTful服务、AOP和国际化等,为Java开发者提供了强大的工具集,使得他们能够高效地构建和管理Web应用程序...
Spring MVC是Spring框架的一个核心模块...这些jar包的使用,使得开发者能够构建出高效、可维护的Web应用,同时利用Spring生态系统中的其他模块,如Spring Data、Spring Security等,进一步增强应用程序的功能和安全性。
5. **RESTful支持**:Spring Web提供对RESTful服务的良好支持,可以通过@RequestMapping等注解定义RESTful端点,处理HTTP方法如GET、POST、PUT、DELETE等。 6. **国际化和主题支持**:Spring Web允许应用提供多语言...
Spring MVC 是一款强大的Java Web开发框架,用于构建RESTful服务和处理HTTP请求。在处理JSON数据时,Spring MVC 提供了便捷的机制。本文将深入探讨Spring MVC中JSON处理的实现流程,包括接收JSON参数和返回JSON响应...
Spring MVC是一种基于Java的实现了MVC设计模式的请求驱动类型的轻量级Web框架,通过DispatcherServlet来对请求进行分发,使得整个开发过程更加快速和敏捷。Spring MVC框架通过一套注解,能够将POJO(普通的Java对象...
在本示例中,我们关注的是Spring框架的3.0版本如何支持RESTful风格的Web服务。REST(Representational State Transfer)是一种网络应用程序的设计风格和开发方式,它基于HTTP协议,强调简洁、无状态和可缓存性。...
- **支持 REST 风格的 URL**:Spring MVC 3.0 引入了对 RESTful 设计的支持,允许使用更加清晰和一致的 URL 结构。 - **添加更多注解**:增加了如 `@RequestBody`, `@ResponseBody`, `@RequestHeader`, `@Cookie...
Spring MVC 是 Spring 框架的一个模块,专为构建基于 Java 的 Web 应用程序而设计。它提供了模型-视图-控制器(MVC)架构,简化了开发过程,允许开发者将业务逻辑与表现层分离。Spring MVC 提供了一系列强大且灵活的...
在Spring MVC框架中,JSON(JavaScript Object Notation)是一种常用的数据交换格式,广泛应用于Web服务接口,特别是RESTful API的设计中。本示例提供了一个完整的返回JSON数据的接口的Spring MVC Demo,帮助开发者...
Spring MVC是Spring框架的一个模块,专门用于构建Web应用程序。在Spring MVC 3.2中,引入了对RESTful服务的良好支持,使得开发基于HTTP的、无状态的服务变得更加简单。REST(Representational State Transfer)是一...
在现代Web应用开发中,Spring MVC作为Java领域最流行的MVC框架之一,为开发者提供了强大的功能,包括构建RESTful API。REST(Representational State Transfer)风格的架构设计是Web服务的一种理想模式,它强调资源...
Spring Web模块是Spring框架的重要组成部分,它为构建RESTful服务、处理HTTP请求、集成Servlet容器等提供了便利。该模块包含以下几个关键组件: 1. `DispatcherServlet`:作为Spring MVC的入口点,负责接收HTTP请求...
在现代Web开发中,Spring MVC框架是Java领域广泛使用的用于构建高效、可维护的Web应用程序的工具。同时,随着RESTful API设计风格的普及,开发者需要将服务暴露为一组资源,通过HTTP方法(如GET、POST、PUT、DELETE...