美文网首页
【转载】SpringMVC系列第4篇:接受参数有多少种方式?

【转载】SpringMVC系列第4篇:接受参数有多少种方式?

作者: f7629e2bca1c | 来源:发表于2021-06-13 17:09 被阅读0次

    原文

    https://mp.weixin.qq.com/s/2iC6f-WWZKvx9DdvmFFTZA

    公众号:路人甲java

    1、本文内容

    Controller 中的方法如何接收 http 请求过来的参数呢?

    具体有哪些方式呢?

    这些就是本文讨论的重点,本文主要围绕下面这些方式来介绍参数的接收

    接收 Servlet 中的参数:HttpServletRequest、HttpServletResponse、HttpSession

    通过方法形参名称接收参数

    通过@RequestParam 接收参数

    通过 1 个对象接收参数

    通过多个对象接收参数

    组合对象接收参数(对象中嵌套对象集合等等)

    通过@PathVariable 接受 url 中的参数

    2、接收 Servlet 中的参数

    比如我们想在方法中用到 servlet 中的对象:HttpServletRequest、HttpServletResponse、HttpSession,那么可以直接在方法的参数中声明这些对象即可,SpringMVC 会自动将这些参数传递进来,用到哪个就声明哪个

    @RequestMapping("/receiveparam/test1.do")

    publicModelAndViewtest1(HttpServletRequest request,

    HttpServletResponse response,

    HttpSession session){

    String name = request.getParameter("name");

    String age = request.getParameter("age");

    String msg = String.format("name:%s,age:%s", name, age);

    System.out.println(msg);

    ModelAndView modelAndView =newModelAndView();

    modelAndView.setViewName("/WEB-INF/view/result.jsp");

    modelAndView.addObject("msg", msg);

    returnmodelAndView;

    }

    对应的表单

    姓名:

    年龄:

    form>

    3、解决乱码问题

    如果大家直接创建一个 springmvc 项目运行上面的案例,会发现 name 为中文的时候,会是乱码,这里需要在 web.xml 中添加下面配置,解决乱码问题

    characterEncodingFilterfilter-name>

    org.springframework.web.filter.CharacterEncodingFilterfilter-class>

    encodingparam-name>

    UTF-8param-value>

    init-param>

    forceRequestEncodingparam-name>

    trueparam-value>

    init-param>

    forceResponseEncodingparam-name>

    trueparam-value>

    init-param>

    filter>

    characterEncodingFilterfilter-name>

    /*url-pattern>

    filter-mapping>

    上面这段配置主要是添加了一个过滤器,这个过滤器会处理所有请求,相当于对所有请求会执行下面操作,而 encoding 我们设置的是 UTF-8

    request.setCharacterEncoding(encoding);

    response.setCharacterEncoding(encoding);

    4、通过方法形参名称接收参数

    表单

    姓名:

    年龄:

    form>

    控制器方法

    /**

    * springmvc调用这个方法之前,会根据方法参数名称,请求中获取参数的值,将其传入

    * 过程:

    * 1、将request.getParameter("name")传递给方法的第1个参数name

    * 2、将Integer.valueOf(request.getParameter("age"))传递给方法的第2个参数age

    *

    *@paramname

    *@paramage

    *@return

    */

    @RequestMapping("/receiveparam/test2.do")

    publicModelAndViewtest2(String name, Integer age){

    String msg = String.format("name:%s,age:%s", name, age);

    System.out.println(msg);

    ModelAndView modelAndView =newModelAndView();

    modelAndView.setViewName("/WEB-INF/view/result.jsp");

    modelAndView.addObject("msg", msg);

    returnmodelAndView;

    }

    这种情况下,form 表单中的参数名称和控制器方法中的参数名称一样,会按照名称一一对应进行赋值。

    5、通过@RequestParam 接收参数

    如果方法的参数名称和表单中的参数名称不一致的时候,可以通过 @RequestParam 注解的 value 属性来指定表单中参数的名称。

    比如下面表单的 2 个名称分别为:pname 和 page

    姓名:

    年龄:

    form>

    对应的方法如下,2 个形参的参数名称分别为 name 和 age,和表单中的名称不一致了,那么可以在方法的参数前面加上@RequestParam 注解,注解的 value 为表单中元素的名称,参数 name 希望接受表单中 pname 的值,那么就需要在 name 这个参数前面加上@RequestParam("pname"),方法的第 2 个参数也一样,加上了@RequestParam("page")

    /**

    * 如果方法的参数名称和表单中的参数名称不一致的时候,可以通过@RequestParam注解的value属性来指定表单中参数的名称

    * 比如:@RequestParam("pname") String name 接收 request.getParameter("pname") 的值

    * 1、将request.getParameter("pname")传递给方法的第1个参数name

    * 2、将Integer.valueOf(request.getParameter("page"))传递给方法的第2个参数age

    *

    *@paramname

    *@paramage

    *@return

    */

    @RequestMapping("/receiveparam/test3.do")

    publicModelAndViewtest3(@RequestParam("pname")String name,

    @RequestParam("page")Integer age)

    {

    String msg = String.format("name:%s,age:%s", name, age);

    System.out.println(msg);

    ModelAndView modelAndView =newModelAndView();

    modelAndView.setViewName("/WEB-INF/view/result.jsp");

    modelAndView.addObject("msg", msg);

    returnmodelAndView;

    }

    @RequestParam用来将请求的参数和方法的参数进行绑定,这个注解还有几个属性,也比较常用,大家熟悉下

    public@interfaceRequestParam {

    //参数名称

    @AliasFor("name")

    Stringvalue()default"";

    //同value属性

    @AliasFor("value")

    Stringname()default"";

    //参数是不是必须的,默认为true,如果请求中没有这个参数,springmvc会报错

    booleanrequired()defaulttrue;

    //默认值

    StringdefaultValue()defaultValueConstants.DEFAULT_NONE;

    }

    6、通过 1 个对象接收参数

    通常方法不要超过 5 个,当 http 请求的参数多的时候,我们可以使用一个对象来接收,对象中的参数名称和 http 请求中的参数名称一致。

    比如有下面表单

    姓名:"name" value="路人"/>

    年龄:"age" value="30"/>

    我们可以定义一个 UserInfoDto 类来接收表单中的参数,这个类中有 2 个属性名称和上面表单中的属性名称一样。

    publicclassUserInfoDto{

    //姓名

    privateString name;

    //年龄

    privateInteger age;

    //省略了get、set方法

    @Override

    publicStringtoString(){

    return"UserModel{"+

    "name='"+ name +'\''+

    ", age="+ age +

    '}';

    }

    }

    对应控制器的代码如下

    /**

    * 传递对象信息,参数比较多的时候,可以通过对象来传递信息

    * 比如表单中2个参数(name、age)

    * 那么可以定义一个类 UserInfoDto(2个属性:name、age) 来接收表单提交的参数

    * 控制器的方法参数为:(UserInfoDto userInfoDto)

    * springmvc调用这个方法的时候,会自动将UserModel创建好,并且将请求中的参数按名称设置到 UserInfoDto 的属性中,然后传递进来

    * 相当于会执行下面代码:

    * UserInfoDto user = new UserInfoDto();

    * user.setName(request.getParameter("name"));

    * user.setAge(Integer.valueOf(request.getParameter("age")));

    * 然后将user对象传给当前方法的第一个参数

    *

    *@paramuserInfoDto

    *@return

    */

    @RequestMapping("/receiveparam/test4.do")

    publicModelAndViewtest4(UserInfoDto userInfoDto){

    String msg = String.format("userDto:%s", userInfoDto);

    System.out.println(msg);

    ModelAndView modelAndView =newModelAndView();

    modelAndView.setViewName("/WEB-INF/view/result.jsp");

    modelAndView.addObject("msg", msg);

    returnmodelAndView;

    }

    7、通过多个对象接收参数

    上面我们将 form 表单有一个对象来接收,实际上也可以用多个对象来接收。

    表单如下

    姓名:

    年龄:

    工作年限:

    年龄:

    form>

    表单中有 4 个元素,我们用 2 个对象来接收,前面 2 个元素用 UserInfoDto 对象来接收,后面 2 个对象用 WorkInfoDto 对象来接收,我们需要定义 2 个类:UserInfoDto 和 WorkInfoDto

    /**

    * 用户基本信息

    */

    publicclassUserInfoDto{

    //姓名

    privateString name;

    //年龄

    privateInteger age;

    //省略了get、set方法

    @Override

    publicStringtoString(){

    return"UserModel{"+

    "name='"+ name +'\''+

    ", age="+ age +

    '}';

    }

    }

    /**

    * 工作基本信息

    */

    publicclassWorkInfoDto{

    //工作年限

    privateInteger workYears;

    //工作地点

    privateString workAddress;

    //省略了get、set方法

    @Override

    publicStringtoString(){

    return"WorkInfoDto{"+

    "workYears="+ workYears +

    ", workAddress='"+ workAddress +'\''+

    '}';

    }

    }

    对应的控制器方法如下

    /**

    * 也可以用多个对象来接收

    * 比如表单有4个元素[name,age,workYear,workAddress]

    * 其中请求的参数 name,age 赋值给UserInfoDto中的2个属性(name,age)

    * 另外2个参数 workYear,workAddress 赋值给WorkInfoDto中的2个属性(workYear,workAddress)

    *

    *@paramuserInfoDto

    *@paramworkInfoDto

    *@return

    */

    @RequestMapping("/receiveparam/test5.do")

    publicModelAndViewtest5(UserInfoDto userInfoDto, WorkInfoDto workInfoDto){

    String msg = String.format("userInfoDto:[%s], workInfoDto:[%s]", userInfoDto, workInfoDto);

    System.out.println(msg);

    ModelAndView modelAndView =newModelAndView();

    modelAndView.setViewName("/WEB-INF/view/result.jsp");

    modelAndView.addObject("msg", msg);

    returnmodelAndView;

    }

    8、组合对象接收参数(对象中嵌套对象、集合等等)

    如下表单

    姓名:"userInfo.name" value="路人"/>

    年龄:"userInfo.age" value="30"/>

    工作年限:"workInfo.workYears" value="10"/>

    年龄:"workInfo.workAddress" value="上海市"/>

    第1份工作公司:

    第1份职位:

    第2份工作公司:

    第2份职位:

    对应的控制器

    @RequestMapping("/receiveparam/test6.do")

    publicModelAndViewtest6(UserDto userDto){

    String msg = String.format("userDto:[%s]", userDto);

    System.out.println(msg);

    ModelAndView modelAndView =newModelAndView();

    modelAndView.setViewName("/WEB-INF/view/result.jsp");

    modelAndView.addObject("msg", msg);

    returnmodelAndView;

    }

    重点要看方法参数UserDto这个类型的结构

    /**

    * 用户信息

    */

    publicclassUserDto{

    //个人基本信息

    privateUserInfoDto userInfo;

    //工作信息

    privateWorkInfoDto workInfo;

    //工作经验(0到n个)

    privateListexperienceInfos;

    //省略了get、set方法

    @Override

    publicStringtoString(){

    return"UserDto{"+

    "userInfo="+ userInfo +

    ", workInfo="+ workInfo +

    ", experienceInfos="+ experienceInfos +

    '}';

    }

    }

    UserDto 类中有 3 个属性,2 个对象,一个 List 集合,再来看看这 3 个类的代码

    /**

    * 用户基本信息

    */

    publicclassUserInfoDto{

    //姓名

    privateString name;

    //年龄

    privateInteger age;

    //省略了get、set方法

    @Override

    publicStringtoString(){

    return"UserModel{"+

    "name='"+ name +'\''+

    ", age="+ age +

    '}';

    }

    }

    /**

    * 工作基本信息

    */

    publicclassWorkInfoDto{

    //工作年限

    privateInteger workYears;

    //工作地点

    privateString workAddress;

    //省略了get、set方法

    @Override

    publicStringtoString(){

    return"WorkInfoDto{"+

    "workYears="+ workYears +

    ", workAddress='"+ workAddress +'\''+

    '}';

    }

    }

    /**

    * 工作经验

    */

    publicclassExperienceInfoDto{

    //公司

    privateString company;

    //职位

    privateString position;

    //省略了get、set方法

    @Override

    publicStringtoString(){

    return"ExperienceInfoDto{"+

    "company='"+ company +'\''+

    ", position='"+ position +'\''+

    '}';

    }

    }

    这里主要注意下集合数据的传递方式,表单中的名称需要有下标,从 0 开始,如下图:

    9、通过@PathVariable 接受 url 中的参数

    有时候我们请求的 url 是下面这样的,有一部是动态的,也就是/userInfo/后面的部分,是 userId,具体 userId 的值是多少我们不知道,此时我们怎么办?

    /userInfo/1

    /userInfo/2

    /userInfo/3

    /userInfo/4

    ...

    /userInfo/{userId}

    这种情况下就可以用到多态 url 了,比如下面控制器的代码,注意@RequestMapping注解的 value 值为/receiveparam/{v1}/{v2}.do,被{}包裹的部分就是动态的部分,方法参数中可以通过@PathVariabl取到 url 动态部分的值。

    /**

    * 动态url:url中可以使用{变量名称}来表示动态的部分,{}包裹的部分可以替换为任意内容

    * 比如:/receiveparam/{v1}/{v2}.do可以接受:/receiveparam/1/2.do、/receiveparam/路人/30.do 等等

    *@PathVariable("变量名称")可以获取到url中动态部分的内容,将其赋值给方法的形参

    * 比如当前方法收到了请求:/receiveparam/路人/30.do

    * 那么方法的第1个参数p1的值为:路人

    * 第2个参数p2的职位30

    *

    *@paramp1

    *@paramp2

    *@return

    */

    @RequestMapping("/receiveparam/{v1}/{v2}.do")

    publicModelAndViewtest7(@PathVariable("v1")String p1, @PathVariable("v2")String p2){

    String msg = String.format("p1:[%s],p2:[%s]", p1, p2);

    System.out.println(msg);

    ModelAndView modelAndView =newModelAndView();

    modelAndView.setViewName("/WEB-INF/view/result.jsp");

    modelAndView.addObject("msg", msg);

    returnmodelAndView;

    }

    请求和值对应关系

    请求 url方法参数 p1 的值方法参数 p2 的值

    /receiveparam/路人/30.do路人30

    /receiveparam/1/2.do12

    上面这些接受参数的方式可以组合,比如下面这样,同时有 servlet 对象和自定义对象

    @RequestMapping("/receiveparam/test8.do")

    publicModelAndViewtest8(HttpServletRequest request, HttpServletResponse response, UserDto userDto)

    10、案例代码及测试用例

    10.1、代码地址

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

    可以下载下来部署到 tomcat 中运行查看上面每个案例的结果。

    10.2、案例代码有两种运行方式

    10.2.1、方式 1:浏览器中查看效果

    将 chat02-receiveparam 模块部署到 tomcat 中,然后访问首页即可看到案例,如下图

    http://localhost:8080/chat02/

    相关文章

      网友评论

          本文标题:【转载】SpringMVC系列第4篇:接受参数有多少种方式?

          本文链接:https://www.haomeiwen.com/subject/srjoeltx.html