之前那篇讲解说配置HiddenHttpMethodFilter即可实现rest风格配置
这里我先把rest的put跟delete主页面代码放一下
<form action="/user" method="post">
<input name="_method" type="hidden" value="delete"/>
<input type="submit" value="Delete">
</form><br>
<form action="/user" method="post">
<input name="_method" type="hidden" value="put"/>
<input type="submit" value="Put">
</form><br>
那么这里我来源码详解一下为什么可以
首先我们需要点开HiddenHttpMethodFilter的源码
看起来一头雾水,其实没关系,我们主要看doFilterInternal方法,我们查看源码
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
HttpServletRequest requestToUse = request;
if ("POST".equals(request.getMethod()) && request.getAttribute("javax.servlet.error.exception") == null) {
String paramValue = request.getParameter(this.methodParam);
if (StringUtils.hasLength(paramValue)) {
String method = paramValue.toUpperCase(Locale.ENGLISH);
if (ALLOWED_METHODS.contains(method)) {
requestToUse = new HiddenHttpMethodFilter.HttpMethodRequestWrapper(request, method);
}
}
}
filterChain.doFilter((ServletRequest)requestToUse, response);
}
几个参数都好理解,request请求,response回复,filterChain过滤器链
HttpServletRequest requestToUse = request;
这句话是创建了一个HttpServletRequest对象,很好理解
接下里就是重点之一了
我们看这个if条件
if ("POST".equals(request.getMethod()) && request.getAttribute("javax.servlet.error.exception") == null)
这里if成立的条件是请求的method必须等于post,这也是我们配置delete跟put时候form标签的method要写成post的原因,另一个要求是javax.servlet.error.exception==null,这个就是要求你不能出现错误
String paramValue = request.getParameter(this.methodParam);
这段话是从request里面获取一个参数,这个参数的key等于this.methodParam,this.methodParam是一个HiddenHttpMethodFilter的成员变量其数值被本类写死
private String methodParam = "_method";
这就是为什么我们要在form标签里面添加
<input name="_method" type="hidden" value="delete"/>
通过这条属性,我们将delete属性跟_method绑定,然后通过request.getParameter将其赋值给了paramValue
if (StringUtils.hasLength(paramValue))
这是调用StringUtils工具类的hasLength确定我们paramValue有长度,也就是该属性存在
String method = paramValue.toUpperCase(Locale.ENGLISH);
这是将paramValue变成大写,然后赋值给method属性,换句话我们在index页面写form配置_method时候不需要区分大小写,这里统一转化为大写
if (ALLOWED_METHODS.contains(method))
这里是判断我们输入给_method的值是符合规范的,要求你不能瞎写只能是delete跟put,单词拼错是不接受的
requestToUse = new HiddenHttpMethodFilter.HttpMethodRequestWrapper(request, method);
这是对request属性就行打包,使用HiddenHttpMethodFilter的HttpMethodRequestWrapper方法,把request请求和我们修改的method组合,用delete替换掉post请求
filterChain.doFilter((ServletRequest)requestToUse, response);
这里就是调用正常的doFilter对其进行处理