APP下载

浅谈基于SpringMVC的REST功能

2016-06-14宋涛徐庆增吕思思

电脑知识与技术 2016年12期

宋涛+徐庆增+吕思思

摘要:数据为王。作为开发人员,我们经常关注于构建优秀的软件来解决业务问题。数据只是我们软件完成工作时要处理的原材料。但是如果你问一下业务人员,数据和软件哪个更重要的话,他们很可能会选择数据。数据是许多业务的命脉。软件通常是可以替换的,但是多年积累的数据是永远不能替换的。近几年来,以信息为中心的表述性状态转移(Representational State Transfer,REST)已成为替换传统SOAP web服务的流行方案,为了帮助spring开发人员使用REST架构模式,spring3.0封装了对REST的良好支持。好消息是Spring对REST的支持是构建在SpringMVC之上的,我们将基于了解的SpringMVC知识来开发处理RESTful资源的控制器。

关键词:Spring MVC;REST; 表述性状态转移

中图分类号:TP393 文献标识码:A 文章编号:1009-3044(2016)12-0086-02

1了解REST

我敢打赌这并不是你第一次涉及或读到REST。近年来,关于REST已经有了许多讨论,在软件开发中你可能会发现有一种很流行的做法。那就是在推动REST替换SOAP web服务的时候,会谈论到SOAP的不足。

诚然,对于许多应用程序而言,使用SOAP可能会有点大材小用了,而REST提供了一个更简单的可选方案。问题在于并不是每个人都清楚地了解REST到底是什么。结果就出现了许多误解。在谈论Spring如何支持REST之前,我们需要对REST是什么达成共识。

2 REST的基本原理

当谈论REET时,有一种常见的错误就是将其视为“基于URL的Web服务”——将REST作为另一种类型的远程过程调用(Remote Procedure Call,RPC)机制,就像SOAP一样,只不过是通过简单的HTTP URL而不是SOAP的大量XML命名空间来触发。

恰好相反,REST与RPC几乎没有任何关系,RPC是面向服务的,并关注与行为和动作。而REST是面向资源的,强调描述应用程序的食物和名词。

此外,尽管URL在RSET中起了关键作用,但他们仅仅是整体的一部分而已。

为了了解REST是什么,我们将它的首字母缩写拆分为不同的组成部分。

1) 表述性(Representational)——REST资源实际上可以用各种形式来进行表述,包括XML,JSON(JavaScript Objict Notation)甚至HTML——最适合资源使用者的任意形式。

2) 状态-(State)—— 当使用了REST的时候,我们更关注资源的状态而不是对资源采取的行为。

3) 转移(Transfer)——REST涉及转移资源数据,它以某一种表述性形式从一个应用转移到了一个应用。

更简洁的讲,REST就是将资源的状态已最合适的形式从服务器端转移到客户端(或者反之)。

基于对REST的这种观点,我尽量避免使用诸如REST服务,REST Web服务或类似的术语,这些术语会不恰当地强调行为。相反,我更愿意强调REST面向资源的本质,并谈论RESTful资源。

3 Spring是如何支持REST的

Spring很早就有导出REST资源的需求。Spring3对Spring MVC的一些增强功能为REST的提供了良好的支持。现在,Spring支持以下方式来开发REST资源。

1) 控制器可以处理所有的HTTP方法,包含4个主要的REST方法:GET,PUT,DELETE,以及POST.

2) 新的@pathVariable注解使得控制器能够处理参数化的URL(将变量输入作为URL的一部分)

3) Spring的表单绑定JSP标签库的标签以及新的hid-denHttpMethodFilter,使得通过HTML表单提交PUT和DELETE请求成为可能,即便在某些浏览器中不支持这些HTTP方法。

4) 通过使用Spring的视图和视图解析器,资源可以以各种形式进行表述,包括将模型数据表现为XML,JSON.atom和RSS的新视图实现。

5) 可以使用新的contentNegotiatingViewResolver来选择最适合客户端的表述。

6) 基于视图的渲染可以使用新的@ResponseBody注解和各种HttpMethod-Converter实现来达到。

7) 类似的,新的@ResponseBody注解以及HttpMethod-Converter实现将传入的HTTP数据转化为传入控制器处理方法的Java对象

8) RestTemplate简化了客户端对REST资源的使用。

4 利用HTTP方法来提交RESTful表单

我们可以利用4个主要的HTTP方法(GET、POST、PUT、以及DELETE)来定义资源的基本操作。通过适当设置@RequestMapping注解的method属性,就可以让DispatcherServlet把不同HTTP方法的请求定向到特定的控制器方法上。Spring MVC能够处理任意HTTP方法的请求——假设客户端能够以要求的HTTP方法发送请求。

这个规划的欠缺之处在于HTML和Web浏览器。非浏览器的客户端,如使用RestTemplate,在发送任意HTTP动作方面并没有什么问题。但是HTML4官方在表单中只支持GET和POST,忽略了PUT,DELETE以及其他的HTTP方法。尽管HTML5和一些新的浏览器支持所有的HTTP方法,但是你不能指望应用程序的用户都使用最新的浏览器。

规避HTML4和较早浏览器缺陷的一个技巧是将PUT或DELETE请求伪装为POST请求。这种方式提交一个浏览器支持的POST请求,但是会有一个隐藏域带有实际HTTP方法的名字。当请求到达服务器端的时候,它会重写为隐藏域指定的请求类型。

Spring通过两个特性来支持POST伪装

1) 通过使用HiddenHttpMethodFilter来进行请求转换;

2) 使用JSP标签渲染隐藏域。

发布真正的请求,当浏览器以PUT或DELETE请求提交渲染所得的表单时,在各个方面它都是一个POST请求。它会作为POST请求通过网络,作为POST请求到达服务器,除非服务器上有些东西打断这个过程,并查看_method隐藏域,否则它将作为POST请求来处理。

同时,控制器的处理方法使用@RequestMapping注解,在等待处理PUT和DELETE请求。HTTP方法的不匹配问题必须在DispatcherServlet查找控制器处理方法之前解决。这就是HiddenHttpMethodFilter所要做的事情。

5 小结

RESTful架构使用web标准来集成应用程序,使得交互变得简单而自然。系统中的资源采用URL进行标识,使用HTTP方法进行管理,并且会以一种或多种适合客户端的方式来表述。

为了响应这些请求,Spring能够将资源背后的数据以最适合客户端的形式展现。对于基于视图的响应,ContentNegotiatingViewResolver能够在多个视图解析器产生的视图中选择最适合客户端期望内容类型的那一个。或者控制器的处理方法使用@ResponseBody注解完全绕过视图解析,并使用信息转换器将返回值转换为客户端的响应。

在REST会话的客户端,Spring提供了RestTemplate,可以在Java代码中基于模板的方式使用RESTful资源。如果客户端是基于浏览器的,Spring的HiddenHttpMethodFilter能够弥补Web浏览器不支持PUT和DELETE方法的不足。