1、简单了解REST
REST(RepresentationalStateTransfer表述性状态转移),是目前最流行的一种互联网软件架构,它结构清晰,符合标准,易于理解,扩展方便。
- 为啥REST如此重要?
- 什么是REST架构 - z
- 状态转换 (StateTransfer):HTTP协议是一个无状态的协议,所有的状态都保存在服务器端,如果客户端想操作服务器,必须通过某种手段,让服务器发生状态改变,而这种转变是建立在表现层之上的。
在HTTP协议里面,有四个表示操作方式的动词 :GET、POST、PUT、DELETE。他们分别对应四种操作 :GET(获取资源)、POST(新建资源)、PUT(更新资源)、DELETE(删除资源)
示例:/order/{id} /order/1 HTTP GET : 得到id=1的order /order/1 HTTP PUT : 更新id=1的order /order/1 HTTP DELETE: 删除id=1的order /order HTTP POST: 新建order
浏览器form表单只支持GET、POST 请求,而DELETE、PUT method属性并不支持。Spring3.0添加了一个过滤器 HiddenHttpMethodFilter,可以将POST 请求转为 PUT、DELETE 请求。
2、HiddenHttpMethodFilter
2.1 HiddenHttpMethodFilter的源码
public class HiddenHttpMethodFilter extends OncePerRequestFilter {
public static final String DEFAULT_METHOD_PARAM = "_method";
private String methodParam = "_method";
public HiddenHttpMethodFilter() {
}
public void setMethodParam(String methodParam) {
Assert.hasText(methodParam, "'methodParam' must not be empty");
this.methodParam = methodParam;
}
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String paramValue = request.getParameter(this.methodParam);
if("POST".equals(request.getMethod()) && StringUtils.hasLength(paramValue)) {
String method = paramValue.toUpperCase(Locale.ENGLISH);
HttpServletRequest wrapper = new HiddenHttpMethodFilter.HttpMethodRequestWrapper(request, method);
filterChain.doFilter(wrapper, response);
} else {
filterChain.doFilter(request, response);
}
}
private static class HttpMethodRequestWrapper extends HttpServletRequestWrapper {
private final String method;
public HttpMethodRequestWrapper(HttpServletRequest request, String method) {
super(request);
this.method = method;
}
public String getMethod() {
return this.method;
}
}
}
1):分析该过滤器的doFilterInternal方法
if("POST".equals(request.getMethod()) && StringUtils.hasLength(paramValue)) {
String method = paramValue.toUpperCase(Locale.ENGLISH);
HttpServletRequest wrapper = new HiddenHttpMethodFilter.HttpMethodRequestWrapper(request, method);
filterChain.doFilter(wrapper, response);
} else {
filterChain.doFilter(request, response);
}
request.getMethod()会返回请求的方式(官方文档的注释:Returns the name of the HTTP method with which this request was made, for example, GET, POST, or PUT. Same as the value of the CGI variable REQUEST_METHOD.)。可以看出 该过滤器只对POST请求进行转换,GET请求不做任何处理,转发给DispatcherServlet
2):
public static final String DEFAULT_METHOD_PARAM = "_method";
private String methodParam = "_method";
--------------
String paramValue = request.getParameter(this.methodParam);
-------------
String method = paramValue.toUpperCase(Locale.ENGLISH);
根据这几条语句可以看出,请求中需包含一个 隐藏表单域(name默认值为_method,value值为PUT或DELETE,value值会转成大写)
3):在获取到 需要转换的 目标请求方式(String method = paramValue.toUpperCase(Locale.ENGLISH);)后,调用该过滤器的静态内部类HttpMethodRequestWrapper的HttpMethodRequestWrapper方法,将请求进行包装,并设置请求方式(method变量值),然后将转换后的请求转发给DispatcherServlet
3、启用HiddenHttpMethodFilter 过滤器
3.1 在web.xml中配置该过滤器
<!-- 配置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>
3.2 表单示例
<form action="springmvc/test" method="post">
<input type="hidden" name="_method" value="PUT">
<input type="submit" value="submit"/>
</form>
参考:
http://docs.oracle.com/javaee/6/api/
https://ke.qq.com/course/159860
http://blog.youkuaiyun.com/qq_35928356/article/category/6944043