Spring MVC 教程-@RequestParam用法及原理详解

作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO

联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬

学习必须往深处挖,挖的越深,基础越扎实!

阶段1、深入多线程

阶段2、深入多线程设计模式

阶段3、深入juc源码解析


阶段4、深入jdk其余源码解析


阶段5、深入jvm源码解析

码哥源码部分

码哥讲源码-原理源码篇【2024年最新大厂关于线程池使用的场景题】

码哥讲源码【炸雷啦!炸雷啦!黄光头他终于跑路啦!】

码哥讲源码-【jvm课程前置知识及c/c++调试环境搭建】

​​​​​​码哥讲源码-原理源码篇【揭秘join方法的唤醒本质上决定于jvm的底层析构函数】

码哥源码-原理源码篇【Doug Lea为什么要将成员变量赋值给局部变量后再操作?】

码哥讲源码【你水不是你的错,但是你胡说八道就是你不对了!】

码哥讲源码【谁再说Spring不支持多线程事务,你给我抽他!】

终结B站没人能讲清楚红黑树的历史,不服等你来踢馆!

打脸系列【020-3小时讲解MESI协议和volatile之间的关系,那些将x86下的验证结果当作最终结果的水货们请闭嘴】

前面没有详细介绍SpringMVC中各种注解的用法,这里准备一一补上,今天来看@RequestParam注解的用法。

1、预备知识

  1.  接口测试利器 HTTP Client
  2. 参数解析器HandlerMethodArgumentResolver解密

2、@RequestParam注解的作用

标注在接口的方法参数上,被标注的参数的值来源于request.getParameterrequest.getParameterValues

3、@RequestParam源码

    @Target(ElementType.PARAMETER)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface RequestParam {
    
    	/**
    	 * 对应request中参数名称
    	 */
    	@AliasFor("name")
    	String value() default "";
    
    	/**
    	 * 同value
    	 */
    	@AliasFor("value")
    	String name() default "";
    
    	/**
    	 * 请求中是否必须有这个参数,默认为true
    	 */
    	boolean required() default true;
    
    	/**
    	 * 默认值
    	 */
    	String defaultValue() default ValueConstants.DEFAULT_NONE;
    
    }

4、案例1:@RequestParam指定name,获取对应参数的值

4.1、案例接口代码

    /**
     * {@link RequestParam}中指定name,用来取name的值对应的请求参数中的值
     *
     * @param name:可以不传递name参数,不传递的时候默认值为ready
     * @param age
     * @param pets
     * @return
     */
    @RequestMapping("/requestparam/test1")
    public Map<String, Object> test1(@RequestParam(value = "name", required = false, defaultValue = "ready") String name, //相当于request.getParameter("name")
                                     @RequestParam("age") int age, //Integer.parseInt(request.getParameter("age"))
                                     @RequestParam("interests") String[] interests, //request.getParameterValues("pets")
                                     @RequestParam("pets") List<String> pets //Arrays.asList(request.getParameterValues("pets"))
    ) {
        Map<String, Object> result = new LinkedHashMap<>();
        result.put("name", name);
        result.put("age", age);
        result.put("interests", interests);
        result.put("pets", pets);
        return result;
    }

4.2、用例1:所有参数都传值

    POST http://localhost:8080/chat18/requestparam/test1
    Content-Type: application/x-www-form-urlencoded
    
    name=路人&age=35&interests=篮球&interests=旅游&pets=小狗&pets=小猫

运行上面用例代码输出

    {
      "name": "路人",
      "age": 35,
      "interests": [
        "篮球",
        "旅游"
      ],
      "pets": [
        "小狗",
        "小猫"
      ]
    }

4.3、用例2:name不传递,会取默认值ready

    POST http://localhost:8080/chat18/requestparam/test1
    Content-Type: application/x-www-form-urlencoded
    
    age=35&interests=篮球&interests=旅游&pets=小狗&pets=小猫

运行上面用例代码输出

    {
      "name": "ready",
      "age": 35,
      "interests": [
        "篮球",
        "旅游"
      ],
      "pets": [
        "小狗",
        "小猫"
      ]
    }

4.4、用来3:required属性为true,不传,则报错

    POST http://localhost:8080/chat18/requestparam/test1
    Content-Type: application/x-www-form-urlencoded

参数都没有传递,而接口要求除name之外的,其他几个参数都必须传递,所以这个案例结果会报400错,提示age参数不存在,这个错误比较常见,大家熟悉下,以后看到了就知道什么问题了。

5、案例2:@RequestParam不指定name,获取所有参数值

当我们想用一个Map来接收所有参数的之后,代码如下,@RequestParam不用指定name的值,参数类型为Map<String,String>,所有请求参数会以参数名称:值的方式丢在Map中。

    /**
     * {@link RequestParam}不指定name,用于接收所有参数的值,
     * 参数类型为Map<String,String>,key为请求中的参数名称,value为值
     *
     * @param paramMap
     * @return
     */
    @RequestMapping("/requestparam/test2")
    public Map<String, String> test2(@RequestParam Map<String, String> paramMap) {
        return paramMap;
    }

运行下面的用例调用上面接口

    ###
    POST http://localhost:8080/chat18/requestparam/test2
    Content-Type: application/x-www-form-urlencoded
    
    name=路人&age=35&interests=篮球&interests=旅游&pets=小狗&pets=小猫

运行输出

    {
      "name": "路人",
      "age": "35",
      "interests": "篮球",
      "pets": "小狗"
    }

interests和pet都是有多个值,上面的结果中都只获取了第一个 值,如果我们想获取所有的值呢,下面看案例3。

6、案例3:@RequestParam不指定name,获取所有参数值

    /**
     * {@link RequestParam}不指定name,用于接收所有参数的值,
     * 参数类型为MultiValueMap<String, String>:key为请求中的参数名称,value为值的集合List<String>
     *
     * @param paramMap
     * @return
     */
    @RequestMapping(value = "/requestparam/test3", produces = MediaType.APPLICATION_JSON_VALUE)
    public MultiValueMap<String, String> test3(@RequestParam MultiValueMap<String, String> paramMap) {
        return paramMap;
    }

这个接口的参数是MultiValueMap类型,这玩意是干啥的?好像很陌生啊,哈哈

再模式的东西,把其源码放出来,瞬间明了了,如下,可以看出来MultiValueMap相当于Map<String,List<String>>

    public interface MultiValueMap<K, V> extends Map<K, List<V>> {
    }

运行下面的用例调用上面接口,注意下面第3行,表示我们期望服务器端返回json格式数据

    POST http://localhost:8080/chat18/requestparam/test3
    Content-Type: application/x-www-form-urlencoded
    Accept: application/json
    
    name=路人&age=35&interests=篮球&interests=旅游&pets=小狗&pets=小猫

运行输出,结果的值比较特别,是一个String类型的数组,这次获取到所有参数的值了。

    {
      "name": [
        "路人"
      ],
      "age": [
        "35"
      ],
      "interests": [
        "篮球",
        "旅游"
      ],
      "pets": [
        "小狗",
        "小猫"
      ]
    }

7、@RequestParam原理

@RequestParam标注的参数的值是有下面2个类处理的,有兴趣了解的建议先看一下上一篇中的:参数解析器HandlerMethodArgumentResolver解密,然后再来看下面2个类的源码就是小意思了。

    org.springframework.web.method.annotation.RequestParamMethodArgumentResolver
    org.springframework.web.method.annotation.RequestParamMapMethodArgumentResolver

8、总结

  • @RequestParam注解用来标注在控制器方法的参数上,springmvc从request中获取请求的值赋值给方法的参数
  • @RequestParam指定name时,可以获取request中指定参数的值,相当于request.getParameter(name)或request.getParameters(name)
  • @RequestParam未指定name,参数类型为:Map<String,String>时,用来接收request中所有参数的值,Map中key为参数名称,value为参数的值
  • @RequestParam未指定name,参数类型为MultiValueMap<String, String>时,用来接收request中所有参数的值,key为请求中的参数名称,value为值的集合List

9、代码位置及说明

9.1、git地址

    https://gitee.com/javacode2018/springmvc-series

9.2、本文案例代码结构说明

  • 10
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值