SpringMVC底层处理请求的类型,分为3类

1、普通参数与基本注解

  • 注解:

@PathVariable、@RequestHeader、@ModelAttribute、@RequestParam、@MatrixVariable、@CookieValue、@RequestBody

  • Servlet API:

WebRequest、ServletRequest、MultipartRequest、HttpSession、javax.servlet.http.PushBuilder、Principal、InputStream、Reader、HttpMethod、Locale、TimeZone、ZoneId

  • 复杂参数:

Map、Errors/BindingResult、Model、RedirectAttributes、ServletResponse、SessionStatus、UriComponentsBuilder、ServletUriComponentsBuilder

  • 自定义对象参数:

可以自动类型转换与格式化,可以级联封装

注解的方式处理页面请求

  • CookieValue(获取Cookid值)、@PathVariable(路径变量)、@RequestHeader(获取请求头)、@RequestParam(获取请求参数)

Controller层

  1. package com.xky.controller;
  2. import org.springframework.web.bind.annotation.*;
  3. import javax.servlet.http.Cookie;
  4. import java.util.HashMap;
  5. import java.util.List;
  6. import java.util.Map;
  7. /**
  8. * @since 2021-02-18 11:31
  9. */
  10. @RestController
  11. public class ParameterTestController {
  12. /**
  13. * @param id 入参
  14. * @param name 入参
  15. * @param pv
  16. * @param userAgent 入参
  17. * @param header 请求头
  18. * @param age 入参
  19. * @param inters 入参
  20. * @param params 入参
  21. * @param cook 单个cookie信息
  22. * @param cookie 整个cookie对象
  23. * @return
  24. */
  25. //@PathVariable、@RequestHeader、@ModelAttribute、@RequestParam、@CookieValue
  26. @GetMapping("/car/{id}/owner/{username}")
  27. public Map<String,Object> getCar(@PathVariable("id") Integer id,
  28. @PathVariable("username") String name,
  29. @PathVariable Map<String,String> pv,
  30. @RequestHeader("User-Agent") String userAgent,
  31. @RequestHeader Map<String,String> header,
  32. @RequestParam("age") Integer age,
  33. @RequestParam("inters")List<String> inters,
  34. @RequestParam Map<String,String> params,
  35. @CookieValue("Idea-661643a5") String cook,
  36. @CookieValue("Idea-661643a5")Cookie cookie){
  37. Map<String, Object> map = new HashMap<>();
  38. // map.put("id", id);
  39. // map.put("name", name);
  40. // map.put("pv", pv);
  41. //获取请求头
  42. // map.put("userAgent", userAgent);
  43. // map.put("headers", header);
  44. //获取数据
  45. map.put("age", age);
  46. map.put("inters", inters);
  47. map.put("params", params);
  48. map.put("_ga", cook);
  49. //将cookie对象中的key和value值打印出来
  50. System.out.println(cookie.getName() + "===>" + cookie.getValue());
  51. System.out.println(cookie);
  52. System.out.println(cook);
  53. return map;
  54. }
  55. }

html页面

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. <h1>welCome!</h1>
  9. <h2>测试基本注解:</h2>
  10. <a href="/car/3/owner/lisi?age=18&inters=basketball&inters=game">/car/{id}/owner/{username}</a><br>
  11. </body>
  12. </html>
  • @RequestBody(获取请求体[POST])

Controller层

  1. package com.xky.controller;
  2. import org.springframework.web.bind.annotation.*;
  3. import javax.servlet.http.Cookie;
  4. import java.util.HashMap;
  5. import java.util.List;
  6. import java.util.Map;
  7. /**
  8. * @since 2021-02-18 11:31
  9. */
  10. @RestController
  11. public class ParameterTestController {
  12. @PostMapping("/save")
  13. public Map postMethod(@RequestBody String content){
  14. Map<String, Object> map = new HashMap<>();
  15. map.put("content", content);
  16. return map;
  17. }
  18. }

html页面

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. <h1>welCome!</h1>
  9. <h2>测试基本注解:</h2>
  10. <form action="/save" method="post">
  11. 测试@RequestBody获取数据库<br/>
  12. 用户名: <input name="userName"/><br>
  13. 邮箱: <input name="email"/>
  14. <input type="submit" value="提交">
  15. </form>
  16. </body>
  17. </html>
  • @RequestAttribute(获取request域属性)

Controller层

  1. package com.xky.controller;
  2. import org.springframework.stereotype.Controller;
  3. import org.springframework.web.bind.annotation.GetMapping;
  4. import org.springframework.web.bind.annotation.RequestAttribute;
  5. import org.springframework.web.bind.annotation.ResponseBody;
  6. import javax.servlet.http.HttpServletRequest;
  7. import java.util.HashMap;
  8. import java.util.Map;
  9. /**
  10. * @since 2021-02-18 14:23
  11. */
  12. @Controller
  13. public class RequestController {
  14. @GetMapping("/goto")
  15. public String goToPage(HttpServletRequest request){
  16. request.setAttribute("msg", "成功了...");
  17. request.setAttribute("code", 200);
  18. return "forward:/success"; //转发到 /success请求
  19. }
  20. @ResponseBody
  21. @GetMapping("/success")
  22. public Map success(@RequestAttribute("msg") String msg,
  23. @RequestAttribute("code") String code,
  24. HttpServletRequest request){
  25. Object msgOne = request.getAttribute("msg");
  26. Map<String, Object> map = new HashMap<>();
  27. map.put("reqMethod_msg", msgOne);
  28. map.put("annotation_msg", msg);
  29. return map;
  30. }
  31. }

之后直接访问localhost:8080/goto,调用goto方法即可:
image.png

  • @MatrixVariable(矩阵变量)

矩阵变量应绑定在路径中,页面开发中cookie仅用了,session怎么使用?
session的jsessionid一般会存放在cookie中每次发请求时会携带,通过这个id找到session对象,如果禁用cookie没有办法使用jsessionid,我们可以通过url重写的方法将jsessionid放在url中,把cookid的值使用矩阵变量的方式进行传递
config配置类

  1. package com.xky.config;
  2. import org.springframework.context.annotation.*;
  3. import org.springframework.web.filter.HiddenHttpMethodFilter;
  4. import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
  5. import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
  6. import org.springframework.web.util.UrlPathHelper;
  7. /**
  8. * web模块配置类
  9. * @since 2021-02-18 10:07
  10. */
  11. @Configuration(proxyBeanMethods = false)
  12. public class WebConfig /*implements WebMvcConfigurer*/ {
  13. /**
  14. * 将_method这个名字换成自定义的
  15. * @return
  16. */
  17. @Bean
  18. public HiddenHttpMethodFilter hiddenHttpMethodFilter(){
  19. HiddenHttpMethodFilter methodFilter = new HiddenHttpMethodFilter();
  20. methodFilter.setMethodParam("_m"); //自定义名字
  21. return methodFilter;
  22. }
  23. /**
  24. * 开启矩阵变量
  25. * 第一种写法:
  26. * 继承 WebMvcConfigurer 接口重写下面的方法
  27. */
  28. /*@Override
  29. public void configurePathMatch(PathMatchConfigurer configurer){
  30. UrlPathHelper urlPathHelper = new UrlPathHelper();
  31. //设置为不移除; 后面的内容,矩阵变量才能生效
  32. urlPathHelper.setRemoveSemicolonContent(false);
  33. configurer.setUrlPathHelper(urlPathHelper);
  34. }*/
  35. /**
  36. * 开启矩阵变量
  37. * 第二种写法
  38. */
  39. @Bean
  40. public WebMvcConfigurer webMvcConfigurer(){
  41. return new WebMvcConfigurer() {
  42. @Override
  43. public void configurePathMatch(PathMatchConfigurer configurer) {
  44. UrlPathHelper urlPathHelper = new UrlPathHelper();
  45. //不移除; 后面的内容,矩阵变量功能就可以生效
  46. urlPathHelper.setRemoveSemicolonContent(false);
  47. configurer.setUrlPathHelper(urlPathHelper);
  48. }
  49. };
  50. }
  51. }

Controller

  1. package com.xky.controller;
  2. import org.springframework.web.bind.annotation.*;
  3. import javax.servlet.http.Cookie;
  4. import java.util.HashMap;
  5. import java.util.List;
  6. import java.util.Map;
  7. /**
  8. * @since 2021-02-18 11:31
  9. */
  10. @RestController
  11. public class ParameterTestController {
  12. //1、语法:/cars/sell;low=34;brand=byd,audi,yd
  13. //2、SpringBoot默认仅用了矩阵变量的功能,要手动开启:
  14. //原理:对于路径的处理,UrlPathHelper进行解析
  15. // removeSemicolonContent(移除分号内容)用来支持矩阵变量,其意思是 是否移除矩阵变量
  16. //3、矩阵变量必须有url路径变量才能被解析
  17. @GetMapping("/cars/{path}")
  18. public Map carsSell(@MatrixVariable("low") Integer low,
  19. @MatrixVariable("brand") List<String> brand,
  20. @PathVariable("path") String path){
  21. Map<String, Object> map = new HashMap<>();
  22. map.put("low", low);
  23. map.put("brand", brand);
  24. map.put("path", path);
  25. return map;
  26. }
  27. //多个参数用同一个参数名的情况下可以使用pathVar路径区别开
  28. @GetMapping("/boss/{bossId}/{empId}")
  29. public Map boss(@MatrixVariable(value = "age",pathVar = "bossId") Integer bossAge,
  30. @MatrixVariable(value = "age",pathVar = "empId") Integer empAge){
  31. Map<String, Object> map = new HashMap<>();
  32. map.put("bossAge", bossAge);
  33. map.put("empAge", empAge);
  34. return map;
  35. }
  36. }

html页面

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. <h1>welCome!</h1>
  9. <h2>测试REST风格:</h2>
  10. <form action="/user" method="get">
  11. <input value="REST-GET 提交" type="submit">
  12. </form>
  13. <form action="/user" method="post">
  14. <input value="REST-POST 提交" type="submit">
  15. </form>
  16. <form action="/user" method="post">
  17. <input type="hidden" name="_method" value="delete">
  18. <input type="hidden" name="_m" value="delete">
  19. <input value="REST-DELETE 提交" type="submit">
  20. </form>
  21. <form action="/user" method="post">
  22. <input type="hidden" name="_method" value="put">
  23. <input value="REST-PUT 提交" type="submit">
  24. </form>
  25. <hr />
  26. <h2>测试基本注解:</h2>
  27. <a href="/car/3/owner/lisi?age=18&inters=basketball&inters=game">/car/{id}/owner/{username}</a><br>
  28. <a href="/car/1">@PathVariable</a><br>
  29. <a href="/car/1">@RequestHeader</a><br>
  30. <a href="/car?brand=byd">@RequestParam-GET</a>
  31. <br>
  32. <a href="/cars/sell;low=34;brand=byd,audi,yd">@RequestParam-GET(矩阵变量)</a><br>
  33. <a href="/cars/sell;low=34;brand=byd,brand=audi;brand=yd">@MatrixVariable(矩阵变量)</a><br>
  34. <a href="/boss/1;age=20/2;age=10">@MatrixVariable(矩阵变量)/boss/{bossId}/{empId}</a><br>
  35. <form action="/save" method="post">
  36. 测试@RequestBody获取数据库<br/>
  37. 用户名: <input name="userName"/><br>
  38. 邮箱: <input name="email"/>
  39. <input type="submit" value="提交">
  40. </form>
  41. <ol>
  42. <li>矩阵变量需要在SpringBoot中手动开启</li>
  43. <li>根据RFC3986的规范,矩阵变量应当绑定在路径变量中!</li>
  44. <li>若是有多个矩阵变量,应当使用英文符号;进行分隔</li>
  45. <li>若是一个矩阵变量有多个值,应当使用英文符号,进行分隔,或只命名多个重复的key即可</li>
  46. <li>如:/cars/sell;low=34;brand=byd,audi,yd</li>
  47. </ol>
  48. </body>
  49. </html>

参数处理原理

  • HandlerMapping种找到能处理请求的Handler(Controller.method())
  • 为当前Handler找一个适配器HandlerAdapter;RequestMappingHandlerAdapter

    1、HandlerAdapter

    image.png

  • 支持方法上标注@RequestMapping

  • 支持函数式编程的

    执行目标方法

    1. mv = ha.handle(processedRequest, response, mappedHandler.getHandler());