@ModelAttribute 注解

@ModelAttribute 注解

试想一个场景,如果我们在修改某个对象的时候,首先该对象是从数据库取出来,展示到前端,但是我们都知道网页有编辑按钮,能够修改个人信息。但是呢,一部分不能修改,比如用户的账号是不能被轻易修改的,而部分属性(密码)是能被修改的。那么在前端的表单提交中,会在服务器接受到一个 new 出一个新的对象,比如 Admin,那么这个时候,我们的不想被修改的属性,账号 account 就为空了呀?

那么如何避免某些属性不被更改,如账号,但又能够修改密码呢?

  1. 使用隐藏表单控件
  2. 使用禁止编辑的样式

但是上面的操作在浏览器,使用 F12 的时候,就会被其他懂行的人恶意修改。并且如果被修改的字段很多,隐藏的表单控件也就不实用了。如何解决呢?

SpringMVC 提供的解决方案是要修改的对象不是 new 出来的,而是从数据库中来,并且需要修改的字段只针对从数据库中来的对象进行修改。需要在方法上使用 @ModelAttribute 注解,但是这个方法并不是普通的请求处理器的目标方法,也就是说这个方法没有 @RequestMapping 注解。而且该注解注解的方法,会在其他所有的目标方法执行之前,都会执行被 @ModelAttribute 注解的方法执行一次。

	@ModelAttribute
	public void testModelAttribute(Map map,String account) {
        AdminDaoImpl adminDaoImpl = new AdminDaoImpl();
        // 从数据库取出对象
		Admin admin = adminDaoImpl.getAdminByAccount(account);
        //放入对象
		map.put("admin",admin);
		return ;
	}
	
	@RequestMapping("testModelAttribute")
	public String testSetAdmin(Admin admin) {
		System.out.println(admin);
		return "success";
	}
	

那么当 表单提交到 testModelAttribute 地址的时候,里面的 account 账号就不为 null,而是有值的。

  • 细节

    • 请求处理器目标方法的入参,默认会通过类名首字母小写的名称在 @ModelAttribute 注解的方法中,添加到请求域的数据中去寻找。

    • 所以如果把 map.put 的 key 改成 ad 等其他的值,那么 testSetAdmin 的入参 admin 就是重新 new 出来的值。

    • 解决方法:使用 @ModelAttribute注解指定查找的属性模型名称。

      	@ModelAttribute
      	public void testModelAttribute(Map map,String account) {
              AdminDaoImpl adminDaoImpl = new AdminDaoImpl();
              // 从数据库取出对象
      		Admin admin = adminDaoImpl.getAdminByAccount(account);
              //放入对象
      		map.put("ad",admin);
      		return ;
      	}
      	
      	@RequestMapping("testModelAttribute")
      	public String testSetAdmin(@ModelAttribute("ad") Admin admin) {
      		System.out.println(admin);
      		return "success.jsp";
      	}
      

运行流程

  1. 执行 @ModelAttribute 注解的方法,从数据库取出对象,把对象放到 Map 中。键为 admin
  2. SpringMVC 从 Map 取出 admin 对象。把表单的请求参数赋值给键 admin 对应的对象属性
  3. SpringMVC 把上述对象传入目标方法的参数
  4. 注意:在 @ModelAttribute 修饰的方法中,放入 Map 时的键需要和目标方法入参类型,的第一个字母小写的字符串一致。

确定目标方法 POJO 类型的入参过程

  1. 确定 map 中的 key

    1. 若目标方法的 POJO 类型没有使用 @ModelAttribute 修饰,则 key 为 POJO 的类名(第一个字母小写)
    2. 若是使用,则 key 为 @ModelAttribute 注解的 value 属性值
  2. 在 implicitModel 中查找 key 对于的对象,

    1. 存在则作为入参传入,如果在 @ModelAttribute 注解的方法保存过,且 key 和 在第一步 确定 map 中的 key 一致,则获取到
  3. 若不存在 implicitModel ,则检查请求解析器(Handler)是否使用了 @SessionAttribute 注解注释

    1. 若使用,且 @SessionAttributes 注解的 value 属性值中包含了 key, 则会从 HttpSession 中来获取 key 所对应的 value 值,存入到目标方法的入参中,不存在则报错
    2. 没有使用 @SessionAttribute 注解 ,则使用反射创建 POJO 类型参数,传入目标方法
  4. SpringMVC 会把 key 和 POJO 类型的对象保存到 implicitModel 中, 进而会保存到 request 中

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值