十SpringBoot2核心技术——web开发(请求参数处理)
Posted 上善若水
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了十SpringBoot2核心技术——web开发(请求参数处理)相关的知识,希望对你有一定的参考价值。
一、请求参数处理
1.1、请求映射
1.1.1、rest使用与原理
- @xxxMapping;
- Rest风格支持(使用HTTP请求方式,动词来表示对资源的操作)
1.以前:/getUser 获取用户 ,/deleteUser 删除用户,/editUser 编辑用户,/saveUser 保存用户;
2.现在:/user GET-获取用户,DELETE-删除用户,PUT-修改用户,POST-保存用户;
3.核心Filter;HiddenHttpMethodFilter
3.1 :用法:表单method=post,隐藏域 _method=put
3.2 :SpringBoot中手动开启
4.扩展:如何把_method这个名字换成我们自己喜欢的。
package com.xbmu.controller;
import org.springframework.web.bind.annotation.*;
@RestController
public class UserController {
// @RequestMapping(value = "/user",method = RequestMethod.GET)
@GetMapping(value = "/user")
public String getUser(){
return "GET-张三";
}
// @RequestMapping(value = "/user",method = RequestMethod.POST)
@PostMapping(value = "/user")
public String saveUser(){
return "POST-张三";
}
// @RequestMapping(value = "/user",method = RequestMethod.PUT)
@PutMapping(value = "/user")
public String putUser(){
return "PUT-张三";
}
// @RequestMapping(value = "/user",method = RequestMethod.DELETE)
@DeleteMapping(value = "/user")
public String deleteUser(){
return "DELETE-张三";
}
}
src/main/resources/static/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Spring Boot2</title>
</head>
<body>
<h1>Spring Boot2,欢迎您</h1>
测试REST风格;
<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="delete">
<input value="REST-DELETE 提交" type="submit"/>
</form>
<form action="/user" method="put">
<input value="REST-PUT 提交" type="submit"/>
</form>
<hr/>
</body>
</html>
源码分析:
在浏览器中,通过表单提交数据的方式只支持两种:GET、POST;想要实现DELETE和PUT的方式,需要使用spring提供的过滤器HiddenHttpMethodFilter。
- 进入webmvc的自动配置类:
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration.
hiddenHttpMethodFilter()方法。
从该方法的@ConditionalOnProperty注解中,可以看出SpringBoot需求手动开启,默认关闭了这个过滤器。
@Bean
@ConditionalOnMissingBean(HiddenHttpMethodFilter.class)
@ConditionalOnProperty(prefix = "spring.mvc.hiddenmethod.filter", name = "enabled")
public OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter() {
return new OrderedHiddenHttpMethodFilter();
}
- org.springframework.web.filter.HiddenHttpMethodFilter
从源码中可以看出:只对表单提交的POST请求做处理,才会把你提交的真正请求参数获取到request.getParameter(this.methodParam)
,然后才会处理你真正提交的PUT、DELETE、PATCH方式的请求。
@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) {
// this.methodParam 的值为: "_method"
String paramValue = request.getParameter(this.methodParam);
if (StringUtils.hasLength(paramValue)) {
String method = paramValue.toUpperCase(Locale.ENGLISH);
// ALLOWED_METHODS 集合中包含:[PUT、DELETE、PATCH]
if (ALLOWED_METHODS.contains(method)) {
requestToUse = new HttpMethodRequestWrapper(request, method);
}
}
}
filterChain.doFilter(requestToUse, response);
}
给表单新增隐藏表单域,传递真正的请求方式
<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>
SpringBoot中开启hiddenmethod 过滤器
server:
port: 8888
spring:
mvc:
hiddenmethod:
filter:
enabled: true # 开启页面表单的Rest功能。默认false,不开启
1.1.2、总结
Rest原理(表单提交要使用REST的时候)
- 表单提交会带上
_mothod=PUT
或_mothod=DELETE
或_mothod=PATCH
- 请求过来被
HiddenHttpMethodFilter
拦截
1.请求是否正常,并且是POST
1.1 获取到_mothod
的值
1.2 兼容以下请求:PUT、DELETE、PATCH
1.3 原生request(post),包装模式requesWrapper重写了getMethod方法,返回的是传入的值。
1.4 过滤器链放行的时候用wrapper。以后的方法调用getMethod是调用requesWrapper的。
Rest使用客户端工具
- 如PostMan直接发送PUT、DELETE等方式请求,无需Filter。
1.2、请求映射原理
SpringMVC功能分析都是从org.springframework.web.servlet.DispatcherServletorg.springframework.web.servlet.DispatcherServlet---->doDispatch(request, response);
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
// Determine handler for the current request.
// 找到当前请求使用哪个Handler(Controller的方法)处理
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
// Determine handler adapter for the current request.
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
...
}
...
}
...
}
RequestMappingHandlerMapping:保存了所有@RequestMapping 和handler的映射规则。
所有的请求映射都在HandlerMapping中。
- SpringBoot自动配置欢迎页WelcomePageHandleMapping。访问 / 能访问到index.html
- SpringBoot自动配置了默认的RequestMappingHandlerMapping
- 请求进来,挨个尝试所有的HandlerMapping,看是否有请求信息。如果有就找到这个请求对应的handler,如果没有就是下一个HandlerMapping
- 我们需要一些自定义的映射处理,我们也可以自己给容器中放HandlerMapping,自定义HandlerMapping。
以上是关于十SpringBoot2核心技术——web开发(请求参数处理)的主要内容,如果未能解决你的问题,请参考以下文章
八SpringBoot2核心技术——web开发(静态资源访问)
八SpringBoot2核心技术——web开发(静态资源访问)
九SpringBoot2核心技术——web开发(静态资源配置原理)
九SpringBoot2核心技术——web开发(静态资源配置原理)