什么是Rest
Rest风格是指使用HTTP请求方式动词来表示对资源的操作
用法
- 开启页面表单的Rest功能
- 页面 form的属性method=post,隐藏域 _method=put、delete等(如果直接get或post,无需隐藏域)
- 编写请求映射
在高版本的springboot中这一项是默认开启的
spring:
mvc:
hiddenmethod:
filter:
enabled: true #开启页面表单的Rest功能
我们的请求都可以用post的形式发送 通过修改一个名字叫 "_method"的隐藏方法的value值 来确定发送到springboot里面最后接收到的请求类型
<form action="/user" method="get">
<input value="REST-GET提交" type="submit" />
</form>
<form action="/user" method="post">
<input value="REST-POST提交" type="submit" />
</form>
<form action="/user" method="post">
<input name="_method" type="hidden" value="DELETE"/>
<input value="REST-DELETE 提交" type="submit"/>
</form>
<form action="/user" method="post">
<input name="_method" type="hidden" value="PUT" />
<input value="REST-PUT提交"type="submit" />
<form>
@GetMapping("/user")
//@RequestMapping(value = "/user",method = RequestMethod.GET)
public String getUser(){
return "GET-张三";
}
@PostMapping("/user")
//@RequestMapping(value = "/user",method = RequestMethod.POST)
public String saveUser(){
return "POST-张三";
}
@PutMapping("/user")
//@RequestMapping(value = "/user",method = RequestMethod.PUT)
public String putUser(){
return "PUT-张三";
}
@DeleteMapping("/user")
//@RequestMapping(value = "/user",method = RequestMethod.DELETE)
public String deleteUser(){
return "DELETE-张三";
}
注释和没注释的两种方法其实都可以
我们看看@PutMapping里面是什么
我们可以看到这其实跟我们注释掉的注解起到的是一样的作用
用post发送不同请求的原理
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()));
/** Default method parameter: {@code _method}. */
public static final String DEFAULT_METHOD_PARAM = "_method";
private String methodParam = DEFAULT_METHOD_PARAM;
/**
* 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;
}
@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);
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()}.
*/
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;
}
}
}
Rest原理(表单提交要使用REST的时候)
- 表单提交会带上
\_method=PUT
- 请求过来被
HiddenHttpMethodFilter
拦截- 请求是否正常,并且是POST
- 获取到
\_method
的值。 - 兼容以下请求;PUT.DELETE.PATCH
- 原生request(post),包装模式requesWrapper重写了getMethod方法,返回的是传入的值。
- 过滤器链放行的时候用wrapper。以后的方法调用getMethod是调用requesWrapper的。
- 获取到
- 请求是否正常,并且是POST
原概就是过滤器会得到 “_method” 这个隐藏表单里面的value
然后根据这个value去修改Controller要接受到的请求 让他们的格式变成
value的值
怎么改变默认的_method
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({
Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({
DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,
ValidationAutoConfiguration.class })
public class WebMvcAutoConfiguration {
...
@Bean
@ConditionalOnMissingBean(HiddenHttpMethodFilter.class)
@ConditionalOnProperty(prefix = "spring.mvc.hiddenmethod.filter", name = "enabled", matchIfMissing = false)
public OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter() {
return new OrderedHiddenHttpMethodFilter();
}
...
}
@ConditionalOnMissingBean(HiddenHttpMethodFilter.class)
意味着在没有HiddenHttpMethodFilter
时,才执行hiddenHttpMethodFilter()
。因此,我们可以自定义filter,改变默认的\_method
。例如:
自定义filter过滤器
@Configuration(proxyBeanMethods = false)
public class WebConfig{
//自定义filter
@Bean
public HiddenHttpMethodFilter hiddenHttpMethodFilter(){
HiddenHttpMethodFilter methodFilter = new HiddenHttpMethodFilter();
methodFilter.setMethodParam("_m");
return methodFilter;
}
}
将\_method
改成_m
。
<form action="/user" method="post">
<input name="_m" type="hidden" value="DELETE"/>
<input value="REST-DELETE 提交" type="submit"/>
</form>
题外话
现在是2022/3/22 的 20:34
看了两三天springboot的课了 才看到
前路漫漫啊
雄关漫道真如铁 而今迈步从头越
慢慢学罢 自己水平有限 学东西也学不快
每天学一点 慢慢积累下来希望我有一天也能成为大佬罢
今天累了 不学了 就这吧