Spring Boot 请求和请求参数处理解析
请求映射
1、rest使用与原理
- @xxxMapping;
- Rest风格支持(使用HTTP请求方式动词来表示对资源的操作)
- 以前:/getUser 获取用户 /deleteUser 删除用户 /editUser 修改用户 /saveUser 保存用户
- 现在: /user GET-获取用户 DELETE-删除用户 PUT-修改用户 POST-保存用户
- 核心Filter;HiddenHttpMethodFilter
- 用法: 表单method=post,隐藏域 _method=put
- SpringBoot中手动开启
- 扩展:如何把_method 这个名字换成我们自己喜欢的。
controller
// @RequestMapping(value = "/user",method = RequestMethod.GET) @GetMapping("/user") public String getUser(){ return "GET-张三"; } // @RequestMapping(value = "/user",method = RequestMethod.POST) @PostMapping("/user") public String saveUser(){ return "POST-张三"; } // @RequestMapping(value = "/user",method = RequestMethod.PUT) @PutMapping("/user") public String putUser(){ return "PUT-张三"; } // @RequestMapping(value = "/user",method = RequestMethod.DELETE) @DeleteMapping("/user") public String deleteUser(){ return "DELETE-张三"; }
页面
测试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="post"> <input name="_method" type="hidden" value="delete"/> 大小写都行 底层源码同意转为大写 <input name="_m" 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>
配置文件
spring: mvc: hiddenmethod: filter: enabled: true #开启页面表单的Rest功能
源码过滤
@Bean @ConditionalOnMissingBean(HiddenHttpMethodFilter.class) @ConditionalOnProperty(prefix = "spring.mvc.hiddenmethod.filter", name = "enabled") public OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter() { return new OrderedHiddenHttpMethodFilter(); }
也可以自定义过滤(给容器注册一个hiddenHttpMethodFilter)
//自定义filter @Bean public HiddenHttpMethodFilter hiddenHttpMethodFilter(){ HiddenHttpMethodFilter methodFilter = new HiddenHttpMethodFilter(); methodFilter.setMethodParam("_m"); return methodFilter; }
Rest原理(表单提交要使用REST的时候)
- 表单提交会带上_method=PUT(PUT大小写都行,底层代码统一转为大写)
- 请求过来被HiddenHttpMethodFilter拦截
- 请求是否正常,并且是POST
- 获取到_method的值。
- 兼容以下请求;PUT.DELETE.PATCH
- 原生request(post),包装模式requesWrapper重写了getMethod方法,返回的是传入的值。
- 过滤器链放行的时候用wrapper。以后的方法调用getMethod是调用requesWrapper的。
Rest使用客户端工具,
- 如PostMan直接发送Put、delete等方式请求,无需Filter。
2、请求映射原理
HttpServlet的继承关系
用doget为例
首先请求调用HttpServlet 中的doget,在子类中FrameworkServlet重写了doget方法
FrameworkServlet类中doget方法
/** * Delegate GET requests to processRequest/doService. * <p>Will also be invoked by HttpServlet's default implementation of {@code doHead}, * with a {@code NoBodyResponse} that just captures the content length. * @see #doService * @see #doHead */ @Override protected final void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { processRequest(request, response); }
processRequest(request, response)方法中调用了doService(request, response);
doService在DispatcherServlet类中重写
doService方法中调用了doDispatch(request, response);
doDispatch方法才是真正的处理所有请求的方法

SpringMVC功能分析都从 org.springframework.web.servlet.DispatcherServlet -> doDispatch()
解析doDispatch()方法
//方法中调用下面这个方法是为了找到当前请求使用哪个Handler(Controller的方法)处理
// Determine handler for the current request. 确定当前请求的处理程序
mappedHandler = getHandler(processedRequest);
/** * Return the HandlerExecutionChain for this request. * <p>Tries all handler mappings in order. * @param request current HTTP request * @return the HandlerExecutionChain, or {@code null} if no handler could be found */ @Nullable protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { if (this.handlerMappings != null) { for (HandlerMapping mapping : this.handlerMappings) { HandlerExecutionChain handler = mapping.getHandler(request); if (handler != null) { return handler; } } } return null; }
handlerMappings中有5个handleMapping
其中 RequestMappingHandlerMapping:保存了所有@RequestMapping 和handler的映射规则。
所有的请求映射都在HandlerMapping中。
- SpringBoot自动配置欢迎页的 WelcomePageHandlerMapping 。访问 /能访问到index.html;
- SpringBoot自动配置了默认 的 RequestMappingHandlerMapping
- 请求进来,挨个尝试所有的HandlerMapping看是否有请求信息。
- 如果有就找到这个请求对应的handler
- 如果没有就是下一个 HandlerMapping
- 我们需要一些自定义的映射处理,我们也可以自己给容器中放HandlerMapping。可以自定义 HandlerMapping
welcomePageHandlerMapping请求”/“访问index.html,下图解析
普通参数与基本注解
26个参数解析器,采用循环遍历的方式找对应的参数解析器,(参数解析器完成第一次加载后,会进到缓存中),15个返回值处理器,最常用的返回值类型:ModelAndView, Model, View, ResponseBody
1.1、注解:
@PathVariable、@RequestHeader、@ModelAttribute、@RequestParam、@MatrixVariable、@CookieValue、@RequestBody
@PathVariable 路径参数传递
// 后台
@RequestMapping("/getInfo/{nameInfo}/info/{info}") public Map getInfo(@PathVariable("nameInfo") String name, @PathVariable("info") String info, @PathVariable Map<String,String> infomap){ Map<String,Object> map = new HashMap<>(); map.put("name",name); map.put("info",info); map.put("infomap",infomap); return map; }
// 前台
<a href="/getInfo/信息名称/info/信息">PathVariable注解</a>
页面显示
@RequestHeader 请求路径头部信息获取
@RequestMapping("/getInfo/{nameInfo}/info/{info}") public Map getInfo(@RequestHeader("User-Agent") String userAgent, @RequestHeader Map<String,String> header){ Map<String,Object> map = new HashMap<>(); map.put("userAgent",userAgent); map.put("header",header); return map; }
页面输出内容
请求的头部信息
@RequestParam 表单提交获取参数
@RequestMapping("/getInfo") public Map getInfo(@RequestParam("name") String name, @RequestParam("age") String age, @RequestParam Map<String,String> info){ Map<String,Object> map = new HashMap<>(); map.put("name",name); map.put("age",age); map.put("info",info); return map; }
<form action="/getInfo"> <input type="hidden" name="name" value="张三"> <input type="hidden" name="age" value="20"> <button type="submit">提交</button> </form>
页面输出
或者
@GetMapping("/info") public Map<String,Object> getCar(@RequestParam("age") Integer age, @RequestParam("inters") List<String> inters, @RequestParam Map<String,String> params){ Map<String,Object> map = new HashMap<>(); map.put("age",age); map.put("inters",inters); map.put("params",params); return map; }
<a href="/info?age=10&inters=basketball&inters=game">信息</a>
页面输出
@CookieValue 获取cookie信息
@GetMapping("/getInfo") public Map getInfo(@CookieValue("pgv_pvi") String pgv_pvi, @CookieValue("pgv_pvi") Cookie cookie){ Map<String,Object> map = new HashMap<>(); map.put("pgv_pvi",pgv_pvi); map.put("cookie",cookie); return map; }
页面输出
@RequestBody 只有post请求时候才能获取请求体 请求的参数内容
@PostMapping("/getInfo") public Map getInfo(@RequestBody String info){ Map<String,Object> map = new HashMap<>(); map.put("info",info); return map; }
<form action="/getInfo" method="post"> <input type="hidden" name="name" value="zhangsan"> <input type="hidden" name="age" value="20"> <button type="submit">提交</button> </form>
页面输出
@RequestAttribute
@Controller public class MyController { @GetMapping("/info1") public String getCar(HttpServletRequest request){ request.setAttribute("name","张三"); request.setAttribute("age",20); return "forward:/success"; } @ResponseBody @GetMapping("/success") public Map<String,Object> getCar(@RequestAttribute("name") String name, @RequestAttribute("age") int age, HttpServletRequest request){ Map<String,Object> map = new HashMap<>(); map.put("annotation_name",name); map.put("annotation_age",age); map.put("request_name",request.getAttribute("name")); return map; } }
http://localhost:8080/info1
返回结果
@MatrixVariable 获取矩阵变量参数
第一种写法
@GetMapping("/getInfo/{path}") public Map getInfo(@PathVariable("path") String path, @MatrixVariable("name") String name, @MatrixVariable("cole")List<String> coleList){ Map<String,Object> map = new HashMap<>(); map.put("path",path); map.put("name",name); map.put("coleList",coleList); return map; }
<a href="/getInfo/info;name=zhangsan;cole=1;cole=san;cole=二">点击</a> 或 <a href="/getInfo/info;name=zhangsan;cole=1,san,二">点击</a>
页面输出
第二种写法
@GetMapping("/getInfo/{bossname}/{staffname}") public Map getInfo(@PathVariable("bossname") String bossname, @MatrixVariable(value = "cole",pathVar = "bossname") String bossncole, @PathVariable("staffname") String staffname, @MatrixVariable(value = "cole",pathVar = "staffname") String staffcole){ Map<String,Object> map = new HashMap<>(); map.put("bossname",bossname); map.put("bossncole",bossncole); map.put("staffname",staffname); map.put("staffcole",staffcole); return map; }
<a href="/getInfo/zhangsan;cole=1/lisi;cole=san">点击</a>
页面输出
@MatrixVariable springboot默认是关闭状态 需要手动开启 开启两种方式
第一种:创建一个配置类 实现WebMvcConfigurer接口 重写configurePathMatch方法
@Configuration public class Container implements WebMvcConfigurer { @Override public void configurePathMatch(PathMatchConfigurer configurer) { UrlPathHelper urlPathHelper = new UrlPathHelper(); // 不移除 ";" 分号后面的内容,矩阵变量功能可以生效 urlPathHelper.setRemoveSemicolonContent(false); WebMvcConfigurer.super.configurePathMatch(configurer); } }第二种:往容器中添加一个WebMvcConfigurer 在方法里创建WebMvcConfigurer
@Bean public WebMvcConfigurer webMvcConfigurer(){ return new WebMvcConfigurer() { @Override public void configurePathMatch(PathMatchConfigurer configurer) { UrlPathHelper urlPathHelper = new UrlPathHelper(); // 不移除 ";" 分号后面的内容,矩阵变量功能可以生效 urlPathHelper.setRemoveSemicolonContent(false); WebMvcConfigurer.super.configurePathMatch(configurer); } }; }
页面开发,cookie禁用了,session里面的内容怎么使用;
session.set(a,b)---> jsessionid ---> cookie ----> 每次发请求携带。url重写:/abc;jsesssionid=xxxx 把cookie的值使用矩阵变量的方式进行传递.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?