11. 数据绑定
11.1 数据绑定介绍
在执行程序时,Spring MVC 会根据客户端请求参数的不同,将请求信息中的信息以一定的方式转换并绑定到控制器类方法参数中,这便是数据绑定。
信息处理的步骤
1)Spring MVC将ServletRequest对象传递给DataBinder
2)将处理方法的入参对象传递给DataBinder
3)DataBinder调用 ConversionService 组件进行数据类型转换和数据格式化工作,并将ServletRequest对象中的信息填充到参数对象中。
4)调用Validator组件对已经绑定了请求消息数据的参数对象进行数据合法性校验
5)校验完成后生成数据绑定结果BindingResult对象,Spring MVC将BindingResult对象的内容赋给处理方法的相应参数
11.2 简单数据绑定
11.2.1 绑定默认数据类型
常用的默认参数类型如下:
HttpServletRequest:通过request对象获取请求信息
HttpServletResponse:通过response处理响应信息
HttpSession:通过session对象得到session中存储的对象
Model/ModelMap作用是将model数据填充到request域
@RequestMapping(value="/selectUser1")
public String selectUser1(HttpServletRequest request){
String id = request.getParameter("id");
System.out.println("id1="+id);
return "success";
}
访问网址
http://localhost:8080/vacation_11_0220/selectUser1?id=1
11.2.2 绑定简单数据类型
简单数据类型就是几种基本数据类型。
@RequestMapping(value="/selectUser2")
public String selectUser2(Integer id){
System.out.println("id2="+id);
return "success";
}
参数中有一个RequestParam注解,可以设置别名
@RequestMapping(value="/selectUser3")
public String selectUser3(@RequestParam(value="user_id")Integer id){
System.out.println("id3="+id);
return "success";
}
此时访问路径为.
http://localhost:8080/vacation_11_0220/selectUser3?user_id=1
11.2.3 绑定POJO类型
当客户端需要传递多个不同类型的参数数据,可将请求参数包装在一个POJO类中
比如填写注册表单
//1.定义用户类
public class User {
private Integer id;
private String username;
private Integer password;
}
//get和set方法省略
编写控制器类
@RequestMapping(value="/toRegister")
public String toRegister( ){
return "register";
}
@RequestMapping(value="/registerUser")
public String registerUser( User user){
String username = user.getUsername();
Integer password = user.getPassword();
System.out.println("username = "+username);
System.out.println("password = "+password);
return "success";
}
首先定义方法转向注册页面,当注册页面点击提交按钮,获取表单提交的信息转向成功界面。
值得注意的是,表单中name属性值必须和POJO类中属性名一致。
<form action="${pageContext.request.contextPath }/registerUser"
method="post">
用户名:<input type="text" name="username" /><br />
密 码:<input type="text" name="password" /><br />
<input type="submit" value="注册"/>
</form>
访问地址
http://localhost:8080/vacation_11_0220/toRegister
为了防止请求参数中的中文乱码问题,使用编码过滤器,在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>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
11.2.4 绑定包装POJO
比如订单和用户,在订单POJO类中包含用户对象。
和上一个相同,定义POJO类,然后定义controller类中的方法
public class Orders {
private Integer ordersId;
private User user;
}//省略get和set方法
然后定义请求方法
@RequestMapping(value="/tofindOrder")
public String toRegister( ){
return "orders";
}
@RequestMapping(value="/findOrdersWithUser")
public String findOrdersWithUser( Orders orders){
Integer orderId = orders.getOrdersId();
String username = orders.getUser().getUsername();
System.out.println("username = "+username);
System.out.println("orderId = "+orderId);
return "success";
}
定义页面
<form action="${pageContext.request.contextPath }/findOrdersWithUser"
method="post">
订单编号:<input type="text" name="ordersId" /><br />
所属用户:<input type="text" name="user.username" /><br />
<input type="submit" value="查询" />
</form>
这里name属性也要和POJO类中的属性名相同
访问路径为
http://localhost:8080/vacation_11_0220/tofindOrder
11.2.5 自定义数据绑定
由于有些数据类型无法直接在后台直接转换,例如日期 数据
这里使用Converter实现转换
首先定义日期转换类DateConverter日期转换类,实现Converter接口
public class DateConverter implements Converter<String, Date> {
// 定义日期格式
private String datePattern = "yyyy-MM-dd HH:mm:ss";
@Override
public Date convert(String source) {
// 格式化日期
SimpleDateFormat sdf = new SimpleDateFormat(datePattern);
try {
return sdf.parse(source);
} catch (ParseException e) {
throw new IllegalArgumentException(
"无效的日期格式,请使用这种格式:"+datePattern);
}
}
}
在配置文件中添加类型转换器的配置
<!-- 显示的装配自定义类型转换器 -->
<mvc:annotation-driven conversion-service="conversionService" />
<!-- 自定义类型转换器配置 -->
<bean id="conversionService" class=
"org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="com.itheima.convert.DateConverter" />
</set>
</property>
</bean>
编写Controller中请求方法
@Controller
public class DateController {
@RequestMapping("/changeDate")
public String changeDate(Date date){
System.out.print(date);
return "success";
}
}
访问路径
http://localhost:8080/vacation_11_0220/changeDate?date=2021-02-20 018:15:15
11.3 复杂数据绑定
11.3.1 绑定数组
在开发过程中,可能会遇到前端请求需要传递到后台一个或者多个相同名称参数的情况,此时采用绑定数组的方式。
需要注意在页面中,name应该相同
<form action="${pageContext.request.contextPath }/deleteUsers"
method="post">
<table width="20%" border=1>
<tr>
<td>选择</td>
<td>用户名</td>
</tr>
<tr>
<td><input name="ids" value="1" type="checkbox"></td>
<td>tom</td>
</tr>
<tr>
<td><input name="ids" value="2" type="checkbox"></td>
<td>jack</td>
</tr>
<tr>
<td><input name="ids" value="3" type="checkbox"></td>
<td>lucy</td>
</tr>
</table>
<input type="submit" value="删除"/>
</form>
编写请求方法
@RequestMapping("/toUser")
public String toUser(){
return "user";
}
@RequestMapping("/deleteUsers")
public String userDelete(Integer[] ids){
if (ids != null) {
for (Integer id : ids) {
System.out.println("删除了"+id);
}
}
else {
System.out.println("ids为空");
}
return "success";
}
访问地址为
http://localhost:8080/vacation_11_0220/toUser
11.3.2 绑定集合
如果批量修改用户信息时,前端请求传递过来的数据可能会批量包含各种类型的数据。针对这种情况,我们可以使用集合数据绑定。
在包装类中定义一个包含用户信息的集合,然后在接受方法中将参数类型定义为该包装类的集合。
定义包装类
package com.itheima.vo;
import java.util.List;
import com.itheima.po.User;
public class UserVO {
private List<User> users;
public List<User> getUsers() {
return users;
}
public void setUsers(List<User> users) {
this.users = users;
}
}
定义接收方法
@RequestMapping("/toEdit")
public String toEdit(){
return "user_edit";
}
@RequestMapping("/editUsers")
public String editUsers(UserVO userList){
List<User> users = userList.getUsers();
for (User user : users) {
if(user.getId() != null)
System.out.println("修改的id"+user.getId()+"用户名"+user.getUsername());
}
return "success";
}
编写前端页面
<form action="${pageContext.request.contextPath }/editUsers"
method="post" id='formid'>
<table width="30%" border=1>
<tr>
<td>选择</td>
<td>用户名</td>
</tr>
<tr>
<td>
<input name="users[0].id" value="1" type="checkbox" />
</td>
<td>
<input name="users[0].username" value="tome" type="text" />
</td>
</tr>
<tr>
<td>
<input name="users[1].id" value="2" type="checkbox" />
</td>
<td>
<input name="users[1].username" value="jack" type="text" />
</td>
</tr>
</table>
<input type="submit" value="修改" />
</form>