1. 参数接收
在servlet中,我们用HttpServletRequest,HttpServletResponse,HttpSession,SpringMVC也支持这三种方式,另外SpringMVC还有自己接收处理器请求的方式:
A. 逐个接收
要求处理器方法的形参名和请求中的参数名一致,同名参数之间进行赋值。
<form action="test/receiveProperty.do" method="post">
姓名:<input type="text" name="name"><br>
年龄:<input type="text" name="age"><br>
<input type="submit" value="提交参数">
</form>
@RequestMapping(value = "/receiveProperty.do")
public ModelAndView doReceiveProperty(String name,int age){
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("name",name);
modelAndView.addObject("age",age);
modelAndView.setViewName("showProperty");
return modelAndView;
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<p>name:${requestScope.get("name")}</p>
<p>age:${requestScope.get("age")}</p>
</body>
</html>
1.SpringMVC的参数赋值流程:
1. 使用request对象的getParameter方法接收请求的参数
2. 通过DispatcherServlet调用请求路径对应的处理器方法,根据参数名成进行赋值(可以自动帮我们完成类型转换)
2.问题1:
由于age我们使用int类型的参数接收,如果我们传递参数的时候,age字段不赋值,则传进去的是空字符串,无法完成类型转换
浮点数也一样,因为这是字符串到int的类型转换,而不是float到int的强制类型转换,“21.6”这种字符串无法被正常解析为int。
处理器错误-400:客户端错误,表示提交请求的参数过程中,发生了错误。
解决办法-1:我们使用包装类替代基本类型,当无法赋值的时候,参数值可以为null
@RequestMapping(value = "/receiveProperty.do")
public ModelAndView doReceiveProperty(String name,Integer age){
ModelAndView modelAndView = new ModelAndView();
System.out.println("age = " + age);
modelAndView.addObject("name",name);
modelAndView.addObject("age",age);
modelAndView.setViewName("showProperty");
return modelAndView;
}
这种办法只能接收空输入,但是对于浮点型或者字符串那些,本身在String转int就会发生错误的数据,是没办法接收的。
解决办法-2:由于传输的数据都是String,因此我们都可以用String来接受
这种办法可以接受任意类型的输入,但是我们接收之后还是要手动去做类型转换,发现无法转换时是不应该让他执行的,而框架发现输入非法时也是拒绝执行的,我们又何必多次一举。相当于框架自动帮助我们隔绝了非法输入。
3.问题2:
Post请求无法正确传递汉字:
但是Get可以:
在Servlet中,我们可以通过设置请求的字符编码方式解决:
public void doPost(HttpServletRequest request){
request.setCharacterEncoding("utf-8");
}
SpringMVC提供了过滤器,帮助我们解决乱码的问题:我们可以自行定义,也可以使用框架提供的CharacterEncodingFilter,我们需要在web.xml中配置
<!--注册声明过滤器,解决post请求乱码的问题-->
<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>
<!--强制request使用设定的编码-->
<init-param>
<param-name>forceRequestEncoding</param-name>
<param-value>true</param-value>
</init-param>
<!--强制response使用设定的编码-->
<init-param>
<param-name>forceResponseEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<!--配置哪些请求需要过滤-->
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<!--/*要求所有的请求先过过滤器-->
<url-pattern>/*</url-pattern>
</filter-mapping>
我们之前说过,SpringMVC实际上取参数、放参数,实际上还是借助了request、response,因此我们只需要指定request和response对象的编码即可。
实际上过滤器的原理就是执行了下述代码:
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String encoding = this.getEncoding();
if (encoding != null) {
if (this.isForceRequestEncoding() || request.getCharacterEncoding() == null) {
request.setCharacterEncoding(encoding);
}
if (this.isForceResponseEncoding()) {
response.setCharacterEncoding(encoding);
}
}
filterChain.doFilter(request, response);
}
实际上就是使用request、response对象的setCharacterEncoding。过滤器的强大之处在于可以对匹配的所有请求设置编码方式而不需要手动在处理器方法中自行设置。
4.传递的参数名和接收的参数名不一致
有时候我们无法修改使得这两个参数名一致,SpringMVC提供了@RequestParam让我们指定传递过来的哪一个参数要赋值给哪一个负责接收的参数。
<p>提交参数</p>
<form action="test/receiveProperty.do" method="post">
姓名:<input type="text" name="rname"><br>
年龄:<input type="text" name="rage"><br>
<input type="submit" value="提交参数">
</form>
@RequestMapping(value = "/receiveProperty.do")
public ModelAndView doReceiveProperty(@RequestParam(value = "rname") String name,@RequestParam(value = "rage") Integer age){
ModelAndView modelAndView = new ModelAndView();
System.out.println("age = " + age);
modelAndView.addObject("name",name);
modelAndView.addObject("age",age);
modelAndView.setViewName("showProperty");
return modelAndView;
}
B. 对象接收
当参数量过多的时候,逐个接收参数就显得十分累赘,SpringMVC也提供了用对象接收的方式,根据上面逐个接收的经验,我们不难猜出,这要求对象中的属性名和请求的参数名一致。
<p>提交对象</p>
<form action="test/receiveObjct.do" method="post">
姓名:<input type="text" name="name"><br>
年龄:<input type="text" name="age"><br>
<input type="submit" value="提交参数">
</form>
package com.zzt.Vo;
public class Student {
private String name;
private Integer age;
public Student() {
System.out.println("----无参构造----");
}
public Student(String name, Integer age) {
System.out.println("----有参构造----");
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
System.out.println("----setName----" + name);
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
System.out.println("----setAge----" + age);
this.age = age;
}
}
@RequestMapping(value = "/receiveObjct.do")
public ModelAndView doReceiveObject(Student student){
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("name",student.getName());
modelAndView.addObject("age",student.getAge());
modelAndView.setViewName("showProperty");
return modelAndView;
}
如上图,SpringMVC首先使用无参构造方法创建了实体类对象,这个过程是在我们提交请求,请求到达对应的处理器方法时才执行的(处理器方法的形参为一个对象),然后,框架会通过调用setter进行属性的注入。
值得注意的是,这种方法必须要求类属性名和请求参数名一致,否则无法正常赋值,因为框架是通过setter知道要注入的请求参数的属性名,再去找对应的请求参数进行注入的,因此如果名称不一致,根本找不到参数,也就无从谈起注入。另外,@RequestParam的作用域仅限于方法参数:@Target({ElementType.PARAMETER})。
2.SpringMVC的MVC
SpringMVC对应三层架构中的V--界面层,用于接收用户请求、返回处理结果。但是SpringMVC之所以叫做SpringMVC,是因为该框架本身也是按照MVC模式构建的,Front controller(前端控制器、中央调度器DispatcherServlet),Controller(后端控制器)、Model(模型,用于存储数据)、View(视图,用于展示数据)。在整个SSM项目的开发中,它还缺少了Spring管理业务层、Mybatis管理持久层。