springMVC学习笔记(3),处理器方法的参数,获取请求的参数值,包括解决中文乱码问题

如果还没有阅读前面的笔记,可以点击下面的链接
springMVC学习笔记(1),开发第一个springMVC的web应用,包含实例的详细步骤和截图

springMVC学习笔记(2),包括三层架构与SSM的关系,springMVC中MVC模式的实现,配置视图解析器。

处理器方法的参数

我们要想获得用户输入的信息,或请求中所携带的其他参数,可以从处理器方法的参数中获得,这些参数会在用户发起请求时,前端控制器分配到指定处理器方法时(即框架系统自动调用该方法),由系统为这些参数赋值。程序员只需要在方法中直接使用这些参数即可。

处理器方法可以包含以下四类参数:

  • HttpServletRequst
  • HttpServletResponse
  • HttpSession
  • 请求中所携带的请求参数
    • 逐个接收
    • 对象接收

这些参数就是处理器方法的形式参数,在定义处理器方法时,需要使用哪种获得参数方式,就在形式参数中定义哪些参数,这些参数的值,会在调用时,由系统自动按一定的规则赋值。

public ModelAndView doSome(形式参数列表){ 
}

例如:

public ModelAndView doSome(HttpServletRequest httpServletRequest,
                               HttpServletResponse httpServletResponse,
                               HttpSession httpSession){
                 
}                   

下面代码,我们来在处理器方法中从HttpServletRequest参数中获得请求中的携带的参数name的值

    @RequestMapping(value = "/some.do")
    public ModelAndView doSome(HttpServletRequest request,
                               HttpServletResponse response,
                               HttpSession session){  
        ModelAndView mv = new ModelAndView();
        mv.addObject("msg","欢迎使用SpringMVC" + request.getParameter("name"));
        mv.addObject("fun","执行的是doSome方法");
        mv.setViewName("show");
        return mv;
    }

我们在地址栏中,直接输入请求,并通过?号来携带参数name=testname
在这里插入图片描述

逐个参数接收

我们也可以直接使用请求中参数的名称作为处理器方法的形参。要求:

  • 形参名与请求中参数的名称一致
  • 顺序没有要求
  • 类型可以是任意基本数据类型,请求参数默认都是使用String类型传递,如果形参使用其他参数类型,框架会在自动赋值时,进行类型转换,如果不能转换成功,则会出错,处理器方法将得不到执行。

例如使用以下代码来接收请求中的多个参数值

    @RequestMapping(value = "/some.do")
    public ModelAndView doSome(String name,int age){  
        ModelAndView mv = new ModelAndView();
        mv.addObject("name",name);
        mv.addObject("age",age);
        mv.setViewName("show");
        return mv;
    }

因为我们修改了Model中的数据,所以,在View(show.jsp)中,也相应的修改一下获取Model值的代码

    <h2>show.jsp从request域中获取数据</h2>
    <h3>姓名:${name}</h3>
    <h3>年龄:${age}</h3>

测试结果:
在这里插入图片描述
当然,如果我们采用form进行POST提交,处理方法是一样的。这里就不做演示了。
但是,我们可能会遇到以下问题:

  • 参数值为空
  • 参数无法自动转换类型
  • 值为中文时为乱码
    首先,当参数值为空时,如果你的形参类型为String类型,空是允许的,只是值为空字符串而以。但是如果当形参为如int类型时,Tomcat会报错误
    在这里插入图片描述
    400错误码,表示请求参数类型不匹配。原因是,在处理器方法的形式参数中,我们定义的是int age
    所以,系统在为形参自动赋值时,会将值自动按形参类型转型,但是,因为值为空,空值无法转型为int类型,所以,报错。这时候,在Tomcat的日志上,其实会显示异常信息

org.springframework.web.method.annotation.MethodArgumentTypeMismatchException: Failed to convert value of type ‘java.lang.String’ to required type ‘int’; nested exception is java.lang.NumberFormatException: For input string: “”

MethodArgumentTypeMismatchException是方法参数类型不匹配异常。
这时,我们可以将形式参数类型设置成为int的包装类型Integer,那么当参数值为空时,会被转型为null,不会报错。

    public ModelAndView doSome(String name,Integer age){
    }

测试结果:
在这里插入图片描述
但是,如果你的形参类型无论为int还是Integer,当参数得到的值为字母或其他字符,还是会出现方法参数类型不匹配异常。
有两种解决办法:

  • 在前端对数据类型和是否为空进行检测,这也是常用办法
  • 申明形式参数类型为String,然后在处理器方法中对数据进行检测和处理。但这其实还是和框架帮你进行类型转换是差不多的。所以,并不建议。

请求参数中文乱码问题

我们现在试试在请求中提交中文。
在这里插入图片描述
可以看出,当使用GET方法提交请求时,中文处理没有问题。但是如果我们改用POST方法进行提交呢?
下面在index.jsp中增加表单,使用POST方法来提交请求

<form action="user/some.do" method="post">
    姓名:<input type="text" name="name" /><br/>
    年龄:<input type="text" name="age" /><br/>
    <button type="submit" >提交</button>
</form>

在这里插入图片描述
点击“提交”按钮后,结果为:
在这里插入图片描述
可以看出,当使用POST方法提交请求时,中文数据出现了乱码。
如果学习过java web开发的同学,应该知道,我们可以在doPost方法中,使用request.setCharacterEncoding(“utf-8”)来指定POST的参数的字符集编码。

    public void doPost(HttpServletRequest request) throws UnsupportedEncodingException {
        request.setCharacterEncoding("utf-8");
    }

但是,这需要为每一个servlet的doPost方法都添加上这一条语句。

实际开发中,我们可以使用过滤器来解决乱码问题。
我们可以直接使用框架中提供的过滤器CharacterEncodingFilter
这个类在以下包中
在这里插入图片描述
由于我们已添加了依赖,所以,可以直接使用。

修改web.xml文件,添加注册过滤器申明

    <filter>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    </filter>

其中,filter-name可以自定义,但一般设置为类名的首字母小写
CharacterEncodingFilter这个类有三个属性,需要在xml文件中来指定属性值。
我们可以通过Ctrl + 鼠标单击类名,来跟踪查看该类的定义,可以看到类的源码

public class CharacterEncodingFilter extends OncePerRequestFilter {
	@Nullable
	private String encoding;
	private boolean forceRequestEncoding = false;
	private boolean forceResponseEncoding = false;
	...
	}
  • encoding:编码名称
  • forceRequestEncoding:是否强制请求使用该编码,默认为false
  • forceResponseEncoding:是否强制响应使用该编码,默认为false

因此,继续修改web.xml文件,设置过滤器的属性值。

    <filter>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceRequestEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
        <init-param>
            <param-name>forceResponseEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>

设置编码为utf-8,并强制要求request和response都使用该编码。

下面再添加过滤器映射,设置哪些请求将应用这个过滤器,我们是将所有请求都使用这个过滤器。

    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

现在,我们设置好了过滤器,/*表示对所有请求都强制过滤器,即使用utf-8编码。我们再看一下效果。
在这里插入图片描述
可以看到。现在不管是通过GET还是POST请求,中文处理都正常了。

校正请求参数名@RequestParam

前面我们要求,处理器方法的形参名称,要求和请求的参数名称相同。如果因为开发的某些原因,不相同,我们该怎么办。

可以使用@RequestParam注解形参,来指定请求中的参数名称。如下:

<form action="user/some.do" method="post">
    姓名:<input type="text" name="myname" /><br/>
    年龄:<input type="text" name="myage" /><br/>
    <button type="submit" >提交</button>
</form>

现在请求参数名称为myname和myage,但我们处理器参数希望继续保持name和age,我们可以为形参加上@RequestParam注解

    public ModelAndView doSome(@RequestParam("myname") String name,
                               @RequestParam("myage") Integer age){
    	...
    }

@RequestParam注解除了value属性外,还有一个required属性,表示,是否一定要有该参数。默认为true,这时,如果请求中缺少这个参数,会出现400错误。

当你认为有些参数在提交时,也可以没有时,可以将required属性设置为false

首先,当没有设置required属性时,这个属性值采用默认值true

当我们直接在地址栏中输入http://localhost:8080/hello/user/some.do,发起请求时,不携带任何参数
在这里插入图片描述
可以看到,会出现400错误,为缺少请求参数。

下面,我们设置required属性值为false

    public ModelAndView doSome(@RequestParam(value = "myname",required = false) String name,
                               @RequestParam(value = "myage",required = false) Integer age){
     	...
	}                              

再尝试在地址栏中直接输入请求URL,不携带任何参数
在这里插入图片描述
没有报错,只是说没有得到相应的参数值。

对象参数接收

当提交的参数较多时,如果继续使用处理器方法形参来列出所有的参数,会不太方便。

我们可以直接把一个自定义类的对象作为处理器方法的形参。这个类的各属性与提交的参数名称相同,类型也可以相一致,并为这些属性添加getter和setter方法,框架在调用这个处理器方法时,会自动产生一个这个类的对象,并通过这个类的setter方法来将提交的参数的值分别为这个对象的各属性赋值,最后,将这个对象通过处理器方法的形参传给处理器方法。程序员可以直接在方法中使用这个对象,并通过这个对象的getter方法来获得各属性值中保存的提交参数值。

我们需要先定义一个类(VO,value object,值对象),比如你是要添加一个学生,提交的信息是学生信息,我们需要创建一个值对象类Student,其需要提交的参数与Student类的各属性名称和类型相同(主要是需要类的属性名称与请求的参数名称要相同)。

例如,我们需要提交的是学生的name和age

<form action="user/some.do" method="post">
    姓名:<input type="text" name="name" /><br/>
    年龄:<input type="text" name="age" /><br/>
    <button type="submit" >提交</button>
</form>

我们可以定义一个VO类Student类,代码如下:

package com.javaoldman.vo;

public class Student {
    private String name;
    private  int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

为了方便打印对象信息,我们还重写了toString方法。

下面,就可以直接使用Student对象作为处理器方法的形参,并直接在方法中使用该对象来获取到提交的各参数值。前面说过,框架会在调用这个处理器方法前,先自动创建一个Student对象,并将请求中携带的参数按名称通过类的setter方法给对象的属性赋值。再将这个对象传给这个处理器方法。

    @RequestMapping(value = "/some.do")
    public ModelAndView doSome(Student student){
        ModelAndView mv = new ModelAndView();
        mv.addObject("student",student);
        mv.setViewName("show");
        return mv;
    }

在View视图文件show.jsp中,修改相应代码如下:

    <h3>姓名:${student.name}</h3>
    <h3>年龄:${student.age}</h3>

因为在View视图中,我们可以直接得到Model中的Student对象,名称叫student。所以,可以通过这个对象来访问相应的属性值。
在这里插入图片描述
通过对象形参来接收请求参数是我们较常用的方式,特别是当提交的参数个数较多时。

下一节,我们再讨论处理器方法的返回值

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Java Man

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值