REST简介
REST 就是将资源的状态以最适合客户端或服务端的形式从服务端转移到客户端(或反过来)。RPC面向服务,REST面向资源。
资源的表述是REST很重要的一个方面。作为Api,常见的表述方式就是JSON和XML。其中,JSON又是如今Web领域更为偏爱的,因为它是JavaScript原生的对象保存格式,非常方便。
Spring表述RESTful的方法
Controller本身并不关心资源如何表述。控制器只返回Java对象,之后由别的模块转换。
Spring提供了两种转换方法:内容协商和消息转换器。而消息转换器是最主要的方式。
HTTP消息转换器
使用消息转换器(message conversion)时,就会跳过模型->视图转换器->视图 那套流程。控制器返回的数据直接被消息转换器转换为所需的类型表示。
Spring提供了多个HTTP消息转换器,例如常见的:
JSON格式 | MappingJacksonHttpMessageConverter 或 MappingJackson2HttpMessageConverter |
XML格式 | Jaxb2RootElementHttpMessageConverter |
RSS格式 | RssChannelHttpMessageConverter |
Atom格式 | AtomFeedHttpMessageConverter |
启用消息转换器
-
@ResponseBody
注解告诉Spring返回的对象将作为资源,DispatcherServlet将根据请求的Accept头使用对应的消息转换器产生响应。 -
@RequestBody
注解告诉Spring根据请求的Content-Type头选择对应的消息转换器将消息转换成Java对象。 - 使用
@RestController
注解应用在Controller类上,可以省略所有的@ResponseBody
注解。
以下内容不用看了。。。
内容协商
方式是使用一个特殊的视图解析器:ContentNegotiatingViewResolver
。它的工作主要分为两个步骤:
- 确定请求的媒体类型;
- 找到适合请求媒体类型的最佳视图。
确定请求的媒体类型
ContentNegotiatingViewResolver
将会:
- 首先查看URL的文件扩展名。
- 查看请求的
Accept
头。 - 如果都没有合法的信息,则采用默认的内容类型。
- 要求其它的视图解析器将返回值渲染为View。然后遍历视图结果列表,找到第一个类型匹配的,返回。
改变默认行为
Spring提供了一个ContentNegotiationManager
类,可以改变ContentNegotiatingViewResolver
的默认行为。使用它有三种方法:
- 直接声明一个
ContentNegotiationManager
类的bean。有点复杂,不建议使用。 - XML方法:通过
ContentNegotiationManagerFactoryBean
类间接创建bean。
<bean id="contentNegotiationManager"
class="org.springframework.http.ContentNegotiationManagerFactoryBean"
p:defaultContentType="application/json">
- Java方法:重载
WebMvcConfigurerAdapter
的configureContentNegotiation()
方法。
public class MyWebConfig extends WebMvcConfigurerAdapter {
@Override
public void configureContentNegotiation(
ContentNegotiationConfigurer configurer) {
configurer.defaultContentType(MediaType.APPLICATION_JSON);
}
@Bean
public ViewResolver cnViewResolver(ContentNegotiationManager cnm) {
ContentNegotiatingViewResolver cnvr = new ContentNegotiatingViewResolver();
cnvr.setContentNegotiationManager(cnm);
return cnvr;
}
使用ContentNegotiationManager
还能同时在配置默认视图类型的基础上,对特定的视图名称渲染为JSON输出。
内容协商的优点和缺点:
优点:它能在Spring MVC之上构建REST资源表述层,控制器代码无需修改。相同的一套控制器方法既能产生HTML内容,又能产生JSON内容。
缺点:无法处理客户端给控制器的资源格式。返回的JSON会添加返回model的key,而这并不是客户端所预期的结果。
总结:不推荐使用。