1 REST 的概念
REST 为“Representational State Transfer”的缩写,中文释义为“表现层状态转换”,REST 不是一种标准,而是一种设计风格。是目前最流行的一种互联网软件架构风格。它倡导结构清晰、符合标准、易于理解、扩展方便的 Web 架构体系,主张严格按照 HTTP 协议中定义的规范设计结构严谨的 Web 应用架构体系。由于 REST 所倡导的理念让 Web 应用更易于开发和维护,更加优雅简洁,所以正得到越来越多网站的采用。
- 资源(Resources):网络上的一个实体,或者说是网络上的一个具体信息。它可以是一段文本、一张图片、一首歌曲、一种服务,总之就是一个具体的存在。可以用一个 URI(统一资源定位符)指向它,每种资源对应一个特定的 URI 。要获取这个资源,访问它的 URI 就可以,因此 URI 即为每一个资源的独一无二的识别符。
- 表现层(Representation):把资源具体呈现出来的形式,叫做它的表现层(Representation)。比如,文本可以用 txt 格式表现,也可以用 HTML 格式、XML 格式、JSON 格式表现,甚至可以采用二进制格式。
- 状态转化(State Transfer):每发出一个请求,就代表了客户端和服务器的一次交互过程。HTTP 协议,是一个无状态协议,即所有的状态都保存在服务器端。因此,如果客户端想要操作服务器,必须通过某种手段,让服务器端发生“状态转化”(State Transfer)。而这种转化是建立在表现层之上的,所以就是 “表现层状态转化”。具体说,就是 HTTP 协议里面,四个表示操作方式的动词:GET、POST、PUT、DELETE。它们分别对应四种基本操作:
- GET 用来获取资源
- POST 用来新建资源
- PUT 用来更新资源
- DELETE 用来删除资源
| HTTP 方法名 | 使用场景 | 资源操作 | 是否幂等 | 是否安全 |
|---|---|---|---|---|
| GET | 从服务器取出资源(一项或多项) | SELECT | 是 | 是 |
| POST | 在服务器新建一个资源 | INSERT | 否 | 否 |
| PUT | 在服务器更新资源(客户端提供完整资源数据) | UPDATE | 是 | 否 |
| DELETE | 从服务器删除资源 | DELETE | 是 | 否 |
- 幂等性:对同一 REST 接口的多次访问,得到的资源状态是相同的。
- 安全性:对该 REST 接口访问,不会使服务器端资源的状态发生改变。
RESTful:就是符合 REST 原则的架构方式即可称为 RESTful。
2 REST 风格的 URL 请求
一般在非 RESTful 风格设计的应用中基本上只使用 POST、GET 类型的 HTTP 动作方法,而在 RESTful 风格设计的应用中充分利用了 HTTP 协议的另外动作方法,统一了数据操作的接口,使得 URL 请求变得简洁化、透明化。

百度百科的请求地址:

3 REST 风格 URL 的好处
①、含蓄,安全:使用问号键值对的方式给服务器传递数据太明显,容易被人利用来对系统进行破坏。使用 REST 风格携带数据不再需要明显的暴露数据的名称。
②、风格统一:URL 地址整体格式统一,从前到后始终都使用斜杠划分各个内容部分,用简单一致的格式表达语义。
③、无状态:在调用一个接口(访问、操作资源)的时候,可以不用考虑上下文,不用考虑当前状态,极大的降低了系统设计的复杂度。
④、严谨,规范:严格按照 HTTP1.1 协议中定义的请求方式本身的语义进行操作。
⑤、简洁,优雅:过去做增删改查操作需要设计 4 个不同的 URL,现在一个就够了。
⑥、丰富的语义:通过 URL 地址就可以知道资源之间的关系,如下所示:
http://localhost:8080/shop
http://localhost:8080/shop/product
http://localhost:8080/shop/product/cellPhone
http://localhost:8080/shop/product/cellPhone/iPhone
4 SpringMVC 对四种请求方式的支持
在@RequestMapping 注解中,我们可以使用 method 熟悉来设置对四种请求的支持:
- @RequestMapping(value = “/get”,method = RequestMethod.GET)
- @RequestMapping(value = “/post”,method = RequestMethod.POST)
- @RequestMapping(value = “/put”,method = RequestMethod.PUT)
- @RequestMapping(value = “/delete”,method = RequestMethod.DELETE)
但是可以发现上面的注解中大体都是相似了,所以 SpringMVC 给我们提供了简化的版本:
- @GetMapping(value = “/get”):对应 GET 请求
- @PostMapping(value = “/post”):对应 POST 请求
- @PutMapping(value = “/put”):对应 PUT 请求
- @DeleteMapping(value = “/delete”):对应 DELETE 请求
注:在 SpringMVC 中对 RESTful 支持,主要通过注解来实现,所以下面再介绍三个相关注解:
- @ResponseBody:响应内容转换为 JSON 格式
- @RequestBody:请求内容转换为 JSON 格式
- @RestContrller:等同@Controller+@ResponsrBody
5 HiddenHttpMethodFilter
浏览器对 REST 的支持:
由于浏览器表单只支持 GET 和 POST 请求,所以为了让浏览器实现 DELETE 和 PUT 请求,Spring 为我们提供了一个过滤器:org.springframework.web.filter.HiddenHttpMethodFilter,可以为我们将 GET 和 POST 请求通过过滤器转化成 PUT 或 DELETE 等其他形式。
5.1 HiddenHttpMethodFilter 配置
在 web.xml 中进行配置,拦截所有资源,注意:它必须作用于解决乱码过滤器 CharacterEncodingFilter 的后面,否则处理乱码的过滤器就会失效。
<!-- 配置 org.springframework.web.filter.HiddenHttpMethodFilter 过滤器 -->
<filter>
<filter-name>hiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>hiddenHttpMethodFilter</filter-name>
<!-- 拦截所有请求 -->
<url-pattern>/*</url-pattern>
</filter-mapping>5.2 HiddenHttpMethodFilter 条件及原理
HiddenHttpMethodFilter 处理 put 和 delete 请求的条件:
a>当前请求的请求方式必须为 post
b>当前请求必须传输请求参数 _method

5.3 HiddenHttpMethodFilter 使用
转 PUT 请求:
POST 请求转为 PUT 请求非常简单,只需在表单隐藏域中通过 _method 请求参数附带请求方式名称即可。
<!-- Themeleaf 代码 -->
<form th:action="@{/user}" method="post">
<input type="hidden" name="_method" value="PUT" />
用户名:<input type="text" name="username" /><br />
密码:<input type="password" name="password" /><br />
<input type="submit" value="修改" /><br />
</form><!-- JSP 代码 -->
<!-- 将POST请求转为PUT请求 -->
<!-- 表单需要按照HiddenHttpMethodFilter的要求来写 -->
<!-- 要求1:请求本身是必须是POST -->
<!-- 要求2:指定新请求方式的请求参数名称必须是_method -->
<form action="${pageContext.request.contextPath}/update/emp" method="post">
<input type="hidden" name="_method" value="PUT" />
.......
</form>转 DELETE 请求:
一般通过点击超链接执行删除操作。
这是一个难点,超链接中没有表单隐藏域,所以需要将超链接转换为表单进行提交,这就需要借助于 JavaScript。
①、在页面上创建一个 action 属性为空的 form 表单
<!-- 将超链接的GET请求转换为DELETE请求 -->
<!-- 1、提供一个通用的表单,用来将GET请求先转换为POST,然后再发送_method请求参数 -->
<!-- action属性不能写死,将来点击哪一个超链接,目标地址就和那个超链接一致 -->
<form id="commonForm" action="" method="post">
<input type="hidden" name="_method" value="delete" />
</form>②、给所有超链接绑定单击响应函数
<script type="text/javascript" src="${pageContext.request.contextPath}/script/jquery-1.7.2.js"></script>
<script type="text/javascript">
$(function () {
$(".removeEmp").click(function () {
// 在单击响应函数中获取当前点击的超链接的URL地址
var targetUrl = this.href;
console.log(targetUrl);
// 通过id获取到表单的jQuery对象,然后设置action属性值,再提交表单
$("#commonForm").attr("action", targetUrl).submit();
// 取消控件的默认行为
return false;
});
});
</script>③、超链接
<a class="removeEmp" href="${pageContext.request.contextPath}/remove/emp/1"
>模拟删除</a
><br />
<a class="removeEmp" href="${pageContext.request.contextPath}/remove/emp/2"
>模拟删除</a
><br />
<a class="removeEmp" href="${pageContext.request.contextPath}/remove/emp/3"
>模拟删除</a
><br />在 web.xml 中注册时,必须先注册 CharacterEncodingFilter,再注册 HiddenHttpMethodFilter。
6 @PathVariable 注解
同 SpringMVC-2 绑定请求方法 中部分。
@PathVariable 作用:通过 URL 地址携带的数据需要通过@PathVariable 注解来获取。它的用法如下:
<a href="${pageContext.request.contextPath}/emp/2">一个参数情况</a><br />//请求路径为:/emp/2
@RequestMapping("/emp/{empId}")
public String testPathVariable(@PathVariable("empId") Integer empId) {
System.out.println("empId="+empId);
return "result";
}对于请求路径中有多个数据,@PathVariable 注解也是支持的。
<a href="${pageContext.request.contextPath}/send/message/tom/tell/jerry"
>多个参数情况</a
><br />//请求路径为:/send/message/tom/tell/jerry
@RequestMapping("/send/message/{foo}/tell/{bar}")
public String sendMessage(@PathVariable("foo") String foo,
@PathVariable("bar") String bar) {
System.out.println("foo = " + foo);
System.out.println("bar = " + bar);
return "target";
}