文章目录
1.开启页面表单的Rest功能
spring:
mvc:
hiddenmethod:
filter:
enabled: true #开启页面表单的Rest功能
2.rest风格支持
rest风格支持(使用HTTP请求方式动词来表示对资源的操作)
- 以前:/getUser 获取用户 /deleteUser 删除用户 /editUser 修改用户 /saveUser 保存用户
- 现在: /user GET-获取用户 DELETE-删除用户 PUT-修改用户 POST-保存用户
核心Filter : HiddenHttpMethodFilter
3.springboot加载rest风格的源码
public class HiddenHttpMethodFilter extends OncePerRequestFilter {
private static final List<String> ALLOWED_METHODS =
Collections.unmodifiableList(Arrays.asList(HttpMethod.PUT.name(),
HttpMethod.DELETE.name(), HttpMethod.PATCH.name()));
/** 默认方法参数: {@code _method}. */
public static final String DEFAULT_METHOD_PARAM = "_method";
private String methodParam = DEFAULT_METHOD_PARAM;
/**
* 设置参数名称以查找HTTP方法。
* @see #DEFAULT_METHOD_PARAM
*/
public void setMethodParam(String methodParam) {
Assert.hasText(methodParam, "'methodParam' must not be empty");
this.methodParam = methodParam;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
HttpServletRequest requestToUse = request;
if ("POST".equals(request.getMethod()) && request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) == null) {
String paramValue = request.getParameter(this.methodParam);
if (StringUtils.hasLength(paramValue)) {
//自动转为大写,大小写忽略
String method = paramValue.toUpperCase(Locale.ENGLISH);
// private static final List<String> ALLOWED_METHODS =
//Collections.unmodifiableList(Arrays.asList(HttpMethod.PUT.name(),
//HttpMethod.DELETE.name(), HttpMethod.PATCH.name()));
//可以看到支持DELETE,PUT,PATCH
if (ALLOWED_METHODS.contains(method)) {
requestToUse = new HttpMethodRequestWrapper(request, method);
}
}
}
filterChain.doFilter(requestToUse, response);
}
/**
* Simple {@link HttpServletRequest} wrapper that returns the supplied method for
* {@link HttpServletRequest#getMethod()}.
* 包装模式的`HttpMethodRequestWrapper`重写了getMethod方法,返回传入的值
*/
private static class HttpMethodRequestWrapper extends HttpServletRequestWrapper {
private final String method;
public HttpMethodRequestWrapper(HttpServletRequest request, String method) {
super(request);
this.method = method;
}
//包装模式的`HttpMethodRequestWrapper`重写了getMethod方法,返回传入的值
@Override
public String getMethod() {
return this.method;
}
}
}
- 自动转为大写,大小写忽略
- 可以看到支持DELETE,PUT,PATCH
- 包装模式的
HttpMethodRequestWrapper
重写了getMethod方法,返回传入的值 - 必须是原生的servlet请求才会拦截,如PostMan直接发送Put、delete等方式请求,无需Filter转换。
- 过滤器链放行的时候用wrapper。以后的方法调用getMethod是调用requesWrapper的。
4.注解
- @PutMapping
- @DeleteMapping
- @GetMapping
- @PostMapping
5.自定义_method 这个名字。
5.1 如果spring容器中没有HiddenHttpMethodFilter则执行以下代码
那么我们可以自己写一个放进去
@Bean
//如果spring容器中没有HiddenHttpMethodFilter则执行以下代码
//那么我们可以自己写一个放进去
@ConditionalOnMissingBean(HiddenHttpMethodFilter.class)
@ConditionalOnProperty(prefix = "spring.mvc.hiddenmethod.filter", name = "enabled", matchIfMissing = false)
public OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter() {
return new OrderedHiddenHttpMethodFilter();
5.2找到原生HiddenHttpMethodFilter类分析
5.3 写HiddenHttpMethodFilter类放入spring容器
package com.fww.demo.controller;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.HiddenHttpMethodFilter;
/**
* @author dongtangqiang
*/
@Configuration(proxyBeanMethods = false)
public class WebConfig {
@Bean
public HiddenHttpMethodFilter HiddenHttpMethodFilter(){
HiddenHttpMethodFilter MethodFilter = new HiddenHttpMethodFilter();
MethodFilter.setMethodParam("_m");
return MethodFilter;
}
}