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的值使用矩阵变量的方式进行传递.
 
posted @   Dabo丶  阅读(1503)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示