一、在配置类中:
@AutoConfiguration(after = { DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,
ValidationAutoConfiguration.class })
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
public class WebMvcAutoConfiguration
提供了一个Filter:
@Bean
@ConditionalOnMissingBean(HiddenHttpMethodFilter.class)
@ConditionalOnProperty(prefix = "spring.mvc.hiddenmethod.filter", name = "enabled")
public OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter() {
return new OrderedHiddenHttpMethodFilter();
}
该Fileter通过条件注解 检查配置文件是否开启参数处理:
spring:
mvc:
hiddenmethod:
filter:
enabled: true
提供一个默认参数名称:
/** Default method parameter: {@code _method}. */
public static final String DEFAULT_METHOD_PARAM = "_method";
同时提供一个接口可以让用户自定义参数名称:
/**
* Set the parameter name to look for HTTP methods.
* @see #DEFAULT_METHOD_PARAM
*/
public void setMethodParam(String methodParam) {
Assert.hasText(methodParam, "'methodParam' must not be empty");
this.methodParam = methodParam;
}
通过doFileter...执行拦截器:
①:表单请求携带参数:_method。
②:进入拦截器后检查请求是否是POST请求,请求是否错误
③:获取请求参数_method。
④:判断请求是否在给定的请求集合内:private static final List<String> ALLOWED_METHODS = Collections.unmodifiableList(Arrays.asList(HttpMethod.PUT.name(), HttpMethod.DELETE.name(), HttpMethod.PATCH.name()));
⑤:将请求包装为:HttpMethodRequestWrapper ,重写getmethod接口
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
//获取请求
HttpServletRequest requestToUse = request;
//判断是否为POST请求,请求是否错误
if ("POST".equals(request.getMethod()) && request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) == null) {
//获取请求方式参数_method
String paramValue = request.getParameter(this.methodParam);
if (StringUtils.hasLength(paramValue)) {
//将请求转为大写
String method = paramValue.toUpperCase(Locale.ENGLISH);
//判断请求是否在给定的请求集合中
if (ALLOWED_METHODS.contains(method)) {
//将请求包装一下,重写了请求的getmethod方法
requestToUse = new HttpMethodRequestWrapper(request, method);
}
}
}
//放行过滤器
filterChain.doFilter(requestToUse, response);
}
重写getmethod:
/**
* Simple {@link HttpServletRequest} wrapper that returns the supplied method for
* {@link HttpServletRequest#getMethod()}.
*/
private static class HttpMethodRequestWrapper extends HttpServletRequestWrapper {
private final String method;
public HttpMethodRequestWrapper(HttpServletRequest request, String method) {
super(request);
this.method = method;
}
@Override
public String getMethod() {
return this.method;
}
}
扩展:如何自定义请求方法参数名称。
自定义配置类:
@Configuration
public class MyConfiger {
@Bean
public HiddenHttpMethodFilter hiddenHttpMethodFilter(){
HiddenHttpMethodFilter hiddenHttpMethodFilter =new HiddenHttpMethodFilter();
//自定义请求方式参数
hiddenHttpMethodFilter.setMethodParam("_m");
return hiddenHttpMethodFilter;
}
}