一、使用场景
以书城的图书修改为例:
1)页面端:显示要修改的图书的信息,图书的所有字段都在。
2)Servlet: 收到修改请求,调用Dao;
String sql = “update book set xxx=?,xxx=?,xxx=?,xxx=?,xxx=? where xxx=?”
是全字段修改的
3)实际场景:实际并不是全修改,只会修改部分字段。
- 不修改的字段一般不会在页面进行展示,或者只能展示不可以修改。
- 为了简单,Controller直接在参数位置写Book对象,springmvc为我们自动封装book(没带的值是null),
- 如果接下来调用了一个全字段更新的Dao操作,那么就会将其他的字段变为null,这是一个问题!!!
4)springmvc是如何封装的
- springmvc创建一个book对象,每个属性都有默认值,string类型的就是null;
- 将请求中所有与book对应的属性一一设置过来;
- 调用全字段更新就有问题。
5)如何保证全字段更新时,只修改页面携带的数据:
- 修改Dao,麻烦
- 让springmvc从数据库中取出一个id为xxx的book对象,请求携带来的属性将原本数据库来的属性覆盖(带了的就修改,没带的就是原本数据里的模样),这下全字段更新就没问题了。
可以使用ModelAttribute实现
二、使用
1、思想:
- springmvc要封装请求参数的对象(book),不应该是自己new出来的,应该是从数据库中拿到的准备好的对象
- 接下来再使用这个对象来封装请求参数。
2、@ModelAttribute注解
标注的位置
1)标注在方法的位置:这个方法就会提前于目标方法先运行。
我们就可以提前查出数据库中的图书信息。
将这个图书信息保存起来,方便下一个方法还能使用:使用Model、ModelMap等
Student student = new Student("马飞", 18, "男", "WHPU");
map.put("student",student);2)标注在参数位置:表明绑定提前方法传回来的Map里的指定的值
@ModelAttribute("student") Student student
@RequestMapping("/bookupdate")
public String handle01(@ModelAttribute("student") Student student){
System.out.println("刚才保存的student数据:"+student);
return "success";
}
@ModelAttribute
public void beforeHandle01(Map<String,Object> map){
//假装从数据库查到一条student数据
Student student = new Student("马飞", 18, "男", "WHPU");
System.out.println("数据已经查出!");
map.put("student",student);
System.out.println("已经将数据保存到Map中");
}
<form action="${pageContext.request.contextPath}/bookupdate" method="post">
姓名:<br>
性别:<input type="text" name="sex"/><br>
年龄:<input type="text" name="age"/><br>
学校:<input type="text" name="school"/><br>
<input type="submit">
</form>
可以看到页面传回来的,是没有username的,按以前的方法,student的username应该为null,而我们使用@ModelAttribute注解后,自动封装变成覆盖之前的数据(new Student("马飞", 18, "男", "WHPU");)
其中,age,sex,school都被页面传过来的值给覆盖了,username保留之前的值。