在执行程序时,SpringMvc会根据客户端请求参数的不同,将请求信息中的信息以一定的方式转换并绑定到控制器类的方法参数中。这种将请求信息数据与后台方法参数建立连接的过程就是springmvc的数据绑定。
在数据绑定过程中,springmvc框架会通过数据绑定组件(Databinder)将请求参数串的内容进行类型转换,然后将转换后的值赋给控制器类中方法的形参,这样后台方法就可以正确绑定并获取客户端请求携带的参数了。整个数据绑定过程如下图所示。
步骤解析如下:
(1)springmvc将ServletRequest对象传递给DataBinder。
(2)将处理方法的入参对象传递给DataBinder。
(3)DataBinder调用ConversionService组件进行数据类型转换、数据格式化等工作,并将ServletRequest对象中的消息填充到参数对象中。
(4)调用Validator组件对已经绑定了请求信息数据的参数对象进行数据合法性校验。
(5)校验完成后会生成数据绑定结果对象BindingResult对象,springmvc会将BindingResult对象中的内容赋给处理方法的相应参数。
以上就是springmvc数据绑定原理。
spirngMVC中的数据绑定类型,分为默认数据类型,简单数据类型,pojo类型,包装的pojo类型,绑定数组类型,绑定集合类型,还有自定定义数据绑定。统称为两大类,即简单数据绑定和复杂数据绑定。
例如:默认数据类型的绑定
常用的默认参数类型如下:
- HTTPServletRequest:通过Reques对象获取请求信息;
- HTTPServletResponse:通过response处理响应信息;
- HttpSession:通过session对象得到session中存储的对象;
- Model/ModelMap:Model是一个接口,ModelMap是一个接口实现,作用是将model数据填充到request域。
例如:
@RequestMapping("/moren")
public String selectUser(HttpServletRequest request) {
String id = request.getParameter("id");
System.out.println(id);
return "success";
}
//简单数据类型绑定,就是指java中几种基本数据类型的绑定,如int、String、Double等。
@RequestMapping("/simple")
public String selecuser(@RequestParam(value = "jason", required = false) Integer id) {
System.out.println("简单数据类型绑定:" + id);
return "success";
}
需要注意的是,有时候前端请求中参数名和后端的处理方法中的形参名不一致,
这时会导致无法进行正确的数据绑定,为此springmvc提供了@RequestParam注解来进行间接数据绑定。
@RequestParam注解主要用于对请求中的参数进行定义,有以下4个属性。
属性 | 说明 |
value |
name属性的别名,这里指参数的名字,即入参的请参数名字,如value=“item_id”表示请求的参数名字为item_id的参数的值将传入。如果只是使用value属性,则可以省略value属性名 |
name | 指定请求头绑定的名称 |
required | 用于指定参数是否必须,默认是true,表示请求中一定要有相应的参数 |
defaultValue | 默认值,表示如果请求中没有同名参数时的默认值 |
//绑定pojo类型:
指的是将所有关联的请求参数封装到一个POJO中,
然后在方法中直接使用该POJO作为形参来完成数据绑定。
@RequestMapping("/toRegister")
public String toRegister() {
return "register";
}
@RequestMapping("/registerUser")
public String registerUser(User user) {
String username = user.getUsername();
Integer password = user.getPassword();
System.out.println("用户名:" + username + " " + "密码:" + password);
return "success";
}
在使用POJO类型数据绑定时,前端请求的参数名(通常为表单提交),
表单内各元素的name属性值必须与要绑定的POJO类中的属性名一样,这样才会绑定成功,
否则后台接收的将是null值。
jsp文件如下:
<%--${pageContext.request.contextPath}相对路径--%>
<%--提交表单,然后发送一个/registerUser请求,控制器捕捉到然后处理--%>
<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>
//绑定包装pojo类型:所谓包装pojo类型就是在一个简单的pojo中包含另一个简单pojo
@RequestMapping("/tofindOrdersWithUser")
public String tofindOrdersWithUser() {
return "orders";
}
//查询订单和用户信息
@RequestMapping("/findOrdersAndUser")
public String findOrdersAndUser(Orders orders) {
Integer id = orders.getOrdersId();
User user = orders.getUser();
String username = user.getUsername();
System.out.println("订单id为:" + id + "用户名为:" + username);
return "success";
}
jsp文件如下
<form action="${pageContext.request.contextPath}/findOrdersAndUser" method="post">
订单编号:<input type="text" name="ordersId"><br>
用户姓名:<input type="text" name="user.username"><br>
<input type="submit" value="查询">
</form>
使用包装pojo类型时,需要满足以下两点:
1.如果查询条件参数是包装类的直接基本属性,则参数直接用对应的属性名;
2.如果查询条件参数是包装类中pojo的子属性,则参数名必须为【对象.属性】,
对象要和包装pojo中的对象属性名一致,属性要和包装pojo中的对象子属性一致。例如:user.username。
//复杂数据类型绑定:即数组的绑定,集合的绑定
//绑定数组:
//主要是处理一些前端请求传递到后端的一个或多个相同名称参数的情况例如批量删除之类的。
@RequestMapping("/toUser")
public String selectusr() {
return "user";
}
@RequestMapping("/deleteUsers")
public String deUser(Integer[] ids) {
if (ids != null) {
for (Integer i : ids
) {
System.out.println("删除了" + i);
}
} else {
System.out.println("ids=null");
}
return "success";
}
jsp文件
<form action="${pageContext.request.contextPath}/deleteUsers" method="post">
<table border="1" width="20%">
<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>jason</td>
</tr>
<tr>
<td><input name="ids" value="3" type="checkbox"></td>
<td>jack</td>
</tr>
</table>
<input type="submit" value="删除">
</form>
//绑定集合:用在批量修改的场景中
public class UserVO{
private List<User> users;
//setter/getter方法
}
@RequestMapping("/toUserEdit")
public String toUserEdit() {
return "user_edit";
}
//处理批量修改请求的方法
@RequestMapping("/editUsers")
public String editUsers(UserVO userList) {
//将所有用户数据封装到集合中
List<User> users = userList.getUsers();
//循环输出所有用户信息
for (User u : users
) {
if (u.getId() != null) {
System.out.println("修改了id为:" + u.getId() +
"的用户名为:" + u.getUsername());
}
}
return "success";
}
需要注意的是:在使用集合数据绑定时,后台方法中不支持直接使用集合形参来进行数据绑定,
所以需要使用包装POJO作为形参,然后在包装POJO中包装一个集合属性。
jsp文件
<form action="${pageContext.request.contextPath}/editUsers" method="post">
<table border="1" width="50%">
<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="jasons" type="text"></td>
</tr>
</table>
<input type="submit" value="修改">
</form>