springmvc框架(三)——参数绑定及自定义类型转换
请求参数的绑定
1. 请求参数的绑定说明
1. 绑定机制
1. 表单提交的数据都是k=v格式的 username=haha&password=123
2. SpringMVC的参数绑定过程是把表单提交的请求参数,作为控制器中方法的参数进行绑定的
3. 要求:提交表单的name和参数的名称是相同的
2. 支持的数据类型
1. 基本数据类型和字符串类型
2. 实体类型(JavaBean)
3. 集合数据类型(List、map集合等)
2. 基本数据类型和字符串类型
1. 提交表单的name和参数的名称是相同的
2. 区分大小写
创建一个param.jsp页面:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <a href="param/testparam?username=haha&password=123">请求参数绑定</a> </body> </html>
创建一个ParamController控制器:
@Controller @RequestMapping("/param") public class ParamController { @RequestMapping("/testparam") public String testParam(String username,String password){ System.out.println("执行了。。。"); System.out.println("用户名:"+username); System.out.println("密码:"+password); return "success"; } }
注意:虽然这里不是用的表单提交参数,而是用的超链接提交附带参数username和password的请求,在处理器(即这里的contoller里的方法)要想获得这两个参数,则必须要保持设置的形参名和请求中的保持一致。
结果为:
3. 实体类型(JavaBean)
1. 提交表单的name和JavaBean中的属性名称需要一致
2. 如果一个JavaBean类中包含其他的引用类型,那么表单的name属性需要编写成:对象.属性 例如:user.name
创建了两个实体类User类和Account类:
User类:
public class User { 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 "User{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
Account类:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public class Account implements Serializable { private String username; private String password; private Double money; private User user; public User getUser() { return user; } public void setUser(User user) { this.user = user; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Double getMoney() { return money; } public void setMoney(Double money) { this.money = money; } @Override public String toString() { return "Account{" + "username='" + username + '\'' + ", password='" + password + '\'' + ", money=" + money + ", user=" + user + '}'; } }
修改param.jsp页面:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <%--<a href="param/testparam?username=haha&password=123">请求参数绑定</a>--%> <form action="param/saveAccount" method="post"> 姓名:<input type="text" name="username"/><br/> 密码:<input type="text" name="password"/><br/> 金额:<input type="text" name="money"/><br/> 用户姓名:<input type="text" name="user.name"/><br/> 用户年龄:<input type="text" name="user.age"/><br/> <input type="submit" value="提交"/> </form> </body> </html>
注意:这里表单的提交方式为 post 。若传入的参数值为中文,则后台获取一定会出现乱码问题,所以需要配置一个过滤器来解决中文乱码问题!!!(若是get方式提交,则不会出现这个问题,这是因为tomcat自带对get方式解决中文乱码的机制!)
在web.xml中配置Spring提供的过滤器类:
<!--配置解决中文乱码的问题--> <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> </filter> <filter-mapping> <filter-name>characterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
修改ParamController:
@Controller @RequestMapping("/param") public class ParamController { /** * 请求参数绑定把数据封装到javabean的类中 */ @RequestMapping("/saveAccount") public String saveAccount(Account account){ System.out.println("执行了。。。"); System.out.println(account); return "success"; } }
注意:这里的方法能够获取页面表单传入的参数是因为参数已经被全部封装进事先定义的JavaBean(即Account类对象)中,而该方法的形参就是该JavaBean实体类的对象,所以就可以直接进行获取了。这也是使用框架便捷性的体现。
测试结果:
4. 给集合属性数据封装
JSP页面编写方式:list[0].属性 或 map['one'].属性
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <%--<a href="param/testparam?username=haha&password=123">请求参数绑定</a>--%> <form action="param/saveAccount" method="post"> 姓名:<input type="text" name="username"/><br/> 密码:<input type="text" name="password"/><br/> 金额:<input type="text" name="money"/><br/> 用户姓名:<input type="text" name="list[0].name"/><br/> 用户年龄:<input type="text" name="list[0].age"/><br/> 用户姓名:<input type="text" name="map['one'].name"/><br/> 用户年龄:<input type="text" name="map['one'].age"/><br/> <input type="submit" value="提交"/> </form> </body> </html>
修改Account类:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public class Account implements Serializable { private String username; private String password; private Double money; private List<User> list; private Map<String,User> map; public List<User> getList() { return list; } public void setList(List<User> list) { this.list = list; } public Map<String, User> getMap() { return map; } public void setMap(Map<String, User> map) { this.map = map; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Double getMoney() { return money; } public void setMoney(Double money) { this.money = money; } @Override public String toString() { return "Account{" + "username='" + username + '\'' + ", password='" + password + '\'' + ", money=" + money + ", list=" + list + ", map=" + map + '}'; } }
修改param.jsp页面:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <form action="param/saveAccount" method="post"> 姓名:<input type="text" name="username"/><br/> 密码:<input type="text" name="password"/><br/> 金额:<input type="text" name="money"/><br/> 用户姓名:<input type="text" name="list[0].name"/><br/> 用户年龄:<input type="text" name="list[0].age"/><br/> 用户姓名:<input type="text" name="map['one'].name"/><br/> 用户年龄:<input type="text" name="map['one'].age"/><br/> <input type="submit" value="提交"/> </form> </body> </html>
其他不改动,运行结果如下:
自定义类型转换器
表单提交的任何数据类型全部都是字符串类型,但是后台定义Integer类型,数据也可以封装上,说明 Spring框架内部会默认进行数据类型转换。
如果想自定义数据类型转换,可以实现Converter的接口。
修改User类,添加一个date属性:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public class User { private String name; private int age; private Date date; public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } 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 "User{" + "name='" + name + '\'' + ", age=" + age + ", date='" + date + '\'' + '}'; } }
在param.jsp中添加一个表单:
<form action="param/saveUser" method="post"> 用户姓名:<input type="text" name="name"/><br/> 用户年龄:<input type="text" name="age"/><br/> 用户生日:<input type="text" name="date"/><br/> <input type="submit" value="提交"/> </form>
在ParamController中添加一个方法:
@RequestMapping("/saveUser") public String saveAccount(User user){ System.out.println("执行了。。。"); System.out.println(user); return "success"; }
在不定义类型转换器的情况下,日期的格式只能写成yyyy/MM/dd,如:
若是写成其他格式,则会报错!
于是,我们自定义一个类型转换器:
/** * 把字符串转换成日期的转换器 */ public class StringToDateConverter implements Converter<String, Date> { /** * 进行类型转换的方法 */ public Date convert(String source){ //判断 if(source==null){ throw new RuntimeException("参数不能为空!"); } try{ DateFormat df = new SimpleDateFormat("yyyy-MM-dd"); //解析字符串 Date date = df.parse(source); return date; }catch (Exception e){ throw new RuntimeException("类型转换错误!"); } } }
该转换器允许日期格式为yyyy-MM-dd。
注册自定义类型转换器,在springmvc.xml配置文件中编写配置:
<!--注册自定义的类型转换器--> <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"> <property name="converters"> <set> <bean class="com.churujianghudezai.utils.StringToDateConverter"/> </set> </property> </bean> <!--配置spring开启注解mvc的支持--> <mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>
可以看到在注解驱动里,我们添加了一个 conversion-service="conversionService" ,因为前面提到过在 SpringMVC.xml 配 置 文 件 中 使 用 <mvc:annotation-driven>替代注解处理器和适配器的配置,这时若要增加转换器的配置,就需要额外添加该条语句。
测试结果为:
额外补充:
在控制器中使用原生的ServletAPI对象
只需要在控制器的方法参数定义HttpServletRequest和HttpServletResponse对象即可。
在jsp页面定义一个超链接:
<a href="param/testServletAPI?username=haha">测试原生Servlet</a>
在控制器中添加一个测试方法:
@RequestMapping("testServletAPI") public String testServlet(HttpServletRequest request, HttpServletResponse response){ System.out.println("已执行..."); System.out.println(request); System.out.println(request.getParameter("username")); HttpSession session=request.getSession(); System.out.println(session); System.out.println(response); return "success"; }
测试结果如下: