SpringMVC 本身是支持 PUT,DELETE 等 HTTP 请求方式的,但由于某些客户端(如:浏览器)并不支持这些,所以 Spring 提供了HiddenHttpMethodFilter这个过滤器来规避这一问题。
一、配置(web.xml)
<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>
二、实现方式
客户端提交请求时必须使用POST方式,然后再多加一个参数 (_method = "PUT"),HiddenHttpMethodFilter 就会隐藏掉POST,在后续逻辑代码中获得的请求方式将都是 PUT 。DELETE 等其他请求方式同理。
另:_method这个参数名是 HiddenHttpMethodFilter 默认的,也可以在web.xml中配置的时候指定自己的参数名称。
/** Default method parameter: {@code _method} */
public static final String DEFAULT_METHOD_PARAM = "_method";
private String methodParam = DEFAULT_METHOD_PARAM;
public void setMethodParam(String methodParam) {
Assert.hasText(methodParam, "'methodParam' must not be empty");
this.methodParam = methodParam;
}
三、实现原理
HiddenHttpMethodFilter的实现原理其实就是新建了个HttpMethodRequestWrapper类,覆写了getMethod()方法,也就是将原来本身的HTTP请求方式(POST)给隐藏掉了。
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
String paramValue = request.getParameter(this.methodParam);
// 这里规定了客户端必须使用POST方式
if ("POST".equals(request.getMethod()) && StringUtils.hasLength(paramValue)) {
String method = paramValue.toUpperCase(Locale.ENGLISH);
// 新建一个 HttpMethodRequestWrapper 实例
HttpServletRequest wrapper = new 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;
}
// 覆写了 getMethod 方法,后续我们调用 getMethod 方法获取到的将都是前端传来的那个假的请求方式,真正的POST请求方式被隐藏掉了。
@Override
public String getMethod() {
return this.method;
}
}