一、了解REST
认识一个新事物(技术)一般应从
(1)是什么
(2)解决了什么问题(有什么好处)
(3)如何使用
这三个层面来入手,关于REST的介绍,让我们也从这三个问题开始。
1.REST是什么
REST(Representational State Transfer)是一种数据为中心的软件架构风格。
与关注行为和处理的传统SOAP Web服务设计不同,REST关注的是要处理的数据,REST面向资源,强调描述应用程序的事物和名词:
表述性(Representational):REST资源可以用各种形式进行表述,XML、JSON、甚至HTML——适合资源使用者的任意形式;
状态(State):当使用REST的时候,我们更关注资源的状态而不是对资源采取的行为;
转移(Transfer):REST中涉及转移资源数据,以合适的表述形式从一个应用转移到另一个应用。
通俗来说,REST就是将资源以最适合客户端的形式从服务器端转移到客户端(或者反过来)。
在REST中,资源通过URL进行识别和定位。REST中的行为是通过HTTP方法来定义的,这些方法通常对应如下的CRUD动作:
Create:POST
Read:GET
Update:PUT或PATCH
Delete:DELETE
也就是说,资源数据在服务器上应该被设计成只是一个“名词”,对资源的操作通过上述CRUD动作来完成,如果一种设计架构是符合REST的上述观点的,那么我们就说它是RESTful架构。
2.REST解决什么问题
(1)REST通过强调资源实现了资源与行为的分离,通过在服务器上设计统一的REST API,很多现代化应用,移动应用客户端或者运行在web浏览器中的JavaScript都可以使用REST API
(2)REST中所有操作都是无状态的,这可以解决资源在集群服务器中状态同步的问题,在一个应用中有可能有多个服务器提供服务,如何维持用户的状态在多个服务器中的一致本身是一个困难的问题。同时也就是说,客户端自身需要负责用户状态的维持,并在每次发送请求时都需要提供足够的信息。
(3)RESTful架构使用Web标准来集成应用程序,使得交互变得简单自然。系统中的资源采用URL标识,使用HTTP方法进行管理,并且会以一种或多种适合客户端的方式进行表述。
3.REST API
RESTful架构的设计主要是REST API的创建,资源表述是REST中很重要的一个方面,它是关于客户端和服务器端针对某一资源是如何通信的。Spring3.0开始就对创建REST API提供了良好的支持,在当前的4.x版本中不断得到发展,Spring支持以下方式创建REST资源:
(1)控制器可以处理所有的HTTP方法;
(2)借助@PathVariable注解,控制器能处理参数化的URL(将变量作为URL的一部分);
(3)借助Spring的视图和视图解析器,资源能够以多种形式进行表述,包括将Model数据渲染为XML、JSON、Atom等;
(4)可以使用ContentNegotiatingViewResolver来选择最适合客户端的表述;
(5)借助@RequestBody和@ResponseBody可以将传入的HTTP数据转化为传入控制器处理方法的Java对象;
(6)借助Rest Template,Spring应用能够方便使用REST资源;
二、SpringMVC创建REST API
控制器本身通常并不关心资源如何表述,控制器以Java对象的方式来处理资源,控制器完成它的工作以后,资源才会被转化为最适合客户端的形式。Spring提供了两种方法:
内容协商(Content negotiation):选择一个视图,它能够将Model渲染为呈现给客户端的表述形式;(不建议使用)
1.确定请求的媒体类型
首先查看URL的文件扩展名,如果得不到任何媒体类型,就会考虑请求中的Accept头部信息,如果都没有,ContentNegotiatingViewResolver将会使用“/”作为默认的内容类型,这意味着客户端必须要接收服务器发送的任何形式的表述。
2.找到适合请求媒体类型的最佳视图
一旦内容类型确定,ContentNegotiatingViewResolver就会将该逻辑视图名解析为渲染模型的View。但它本身不会解析视图,而是委托给其他的视图解析器。
优势与限制:ContentNegotiatingViewResolver最大的优势在于,它在SpringMVC之上构建了REST资源表述层,控制器代码无需修改。限制是:作为ViewResolver的实现,它只能决定资源如何渲染到客户端,并不涉及客户端要发送什么样的表述给控制器使用,如果客户端发送JSON或XML,它就无法提供帮助了。另一个小问题,选中的View是渲染Model给客户端,而不是资源。客户端请求JSON格式的对象数组时,响应可能是对象数组封装成属性的对象。
消息转换器(Message conversion):通过消息转换器将控制器返回的对象转换为呈现给客户端的表述形式。
Spring自带了各种各样的转换器,大部分都是自动注册,不需要Spring配置,但为了支持它们,需要添加一些库到应用程序的类路径下。
正常情况下,处理方法返回Java对象(除String和逻辑View)时,这个对象会放在Model中并在视图中渲染使用。但使用消息转换,我们需要告诉Spring跳过正常的Model/View流程使用消息转换器。
@ResponseBody注解会告知Spring,我们要将返回的对象作为资源发送给客户端,并将其转换为客户端可接受的表述形式。具体讲,DispatchServlet将会考虑请求中Accept头部信息,并查找能够为客户端提供所需表述形式的消息转换器。
@RequestBody注解告诉Spring查找一个消息转换器,将来自客户端的资源表述转换为对象。
@RequestMapping(method=RequestMethod.GET,produces="application/json")
public @ResponseBody ResData hello(@RequestBody CliData cli)
{
return new ResData.save(cli);
//样例代码,主要注意两个注解的书写位置
}
为控制器设置默认消息转换
Spring4.0引入了@RestController注解,在控制器类上使用它代替@Controller,Spring会为该控制器的所有处理方法应用消息转换功能,就不必为每个方法都添加@ResponseBody了。
提供资源以外的其他内容
@ResponseEntity注解作为@Response Body的替代方案,控制器方法可以返回一个Response Entity对象,其中可以包含response相关的元数据(如头部信息和状态码)。