springBoot对REST支持源码解析
一、在配置类中:
@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接口
@Overrideprotected 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) {//获取请求方式参数_methodString 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;}@Overridepublic String getMethod() {return this.method;}}
扩展:如何自定义请求方法参数名称。
自定义配置类:
@Configuration
public class MyConfiger {@Beanpublic HiddenHttpMethodFilter hiddenHttpMethodFilter(){HiddenHttpMethodFilter hiddenHttpMethodFilter =new HiddenHttpMethodFilter();//自定义请求方式参数hiddenHttpMethodFilter.setMethodParam("_m");return hiddenHttpMethodFilter;}
}