1、rest使用与原理
Rest风格支持使用HTTP请求方式动词来表示对资源的操作
举例:在之前的请求参数处理中我们采用下面的形式
/getUser 获取用户 /deleteUser 删除用户 /editUser 修改用户 /saveUser 保存用户
Rest风格如下所示
/user GET-获取用户 DELETE-删除用户 PUT-修改用户 POST-保存用户。
可以看到rest风格根据请求方式来表示对资源的操作。
下面进行测试:
在controller包下新建一个WebController
package com.yjh.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class WebController {
@RequestMapping(value="/user",method = RequestMethod.GET)
public String getUser()
{
return "GET-张三";
}
@RequestMapping(value="/user",method = RequestMethod.POST)
public String postUser()
{
return "POST-张三";
}
@RequestMapping(value="/user",method = RequestMethod.PUT)
public String putUser()
{
return "PUT-张三";
}
@RequestMapping(value="/user",method=RequestMethod.DELETE)
public String deleteUser()
{
return "DELETE-张三";
}
}
index.html中添加表单提交代码
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<p>这是欢迎界面</p>
测试REST风格
<form action="/user" method="get">
<input value="REST-GET 提交" type="submit">
</form>
<form action="/user" method="post">
<input value="REST-POST 提交" type="submit">
</form>
<form action="/user" method="post">
<input value="REST-PUT 提交" type="submit">
</form>
<form action="/user" method="post">
<input value="REST-DELETE 提交" type="submit">
</form>
</body>
</html>
依次点击每个按钮进行测试
可以发现与我们预期的不同,PUT提交和DELETE提交最后都变成POST提交了。
修改index.html,将后两个表单的method都改为post提交,并在表单内部添加一行_method的参数,类型为hidden,值为put或者delete。添加完毕后重新测试
在配置文件中需要添加如下配置,重新运行可以获得正确结果。
spring.mvc.hiddenmethod.filter.enabled=true
2、Rest原理(针对表单)
上述代码的改动的原理我们可以从源代码中深挖一下,打开WebMvcAutoConfiguration找到如下图部分,其中红色框说明配置文件中的配置方式,当配置文件中enabled为true则装配该组件否则不装配。
继续深挖代码,进入OrderedHiddenHttpMethodFilter,该类继承了HiddenHttpMethodFilter
继续进入HiddenHttpMethodFilter,找到如下代码并打断点调试研究代码。
下图将这部分代码中的每一行代码的作用都标记上了,也解释了第一部分代码修改的原因。
(1)index.html中为什么put和delete的提交方式为POST
因为源代码中就是判断是否为POST,只有是POST才进入if的判断体内部继续操作。
(2)为什么要在form表单中添加<input name="_method" type="hidden" value="put">这段代码
从源码中进入if语句后,需要获取this.methodParam的请求参数,点进this.methodParam可以看到如下代码:this.methodParam就是"_method"。后续包装就是将_method的值进行包装。
(3)ALLOWED_METHOD允许的提交方式有哪些,也就是说哪些提交方式能够进行包装,点进ALLOWED_METHOD可以看到同三种,分别是:PUT、DELETE、PATCH
3、总结
(1) 表单提交要使用REST的时候,当提交方式是PUT、DELETE、PATCH时,表单提交需要带上_method参数
(2)请求过来被HiddenHttpMethodFilter拦截
判断请求是否正常,并且是POST
获取到_method的值。
兼容以下请求;PUT.DELETE.PATCH
原生request(post),包装模式requesWrapper重写了getMethod方法,返回的是传入的值。
过滤器链放行的时候用wrapper。以后的方法调用getMethod是调用requesWrapper的
(3)上述只针对表单提交,如果采用第三方软件,例如POSTMAN提交的时候,是不经过该段代码的。