• 011 处理模型数据时@ModelAttribute的使用


    一:说明

    1.使用场景

      在下面的场景中:

      使用new对象时,最后的效果是两个被赋值了,但是还有一个值是空值的,这个不符合只更新两个值,另一个值不变的情况。

      

      正确的做法:

      三个值得数据不是new出来的,而是从数据库中获取。

      这种做法适合于本文的注解。

      

    2.注解的知识点

      有@ModelAttribute标记的方法,会在每个目标方法执行之前被SpringMVC调用。

    二:程序

    1.bean对象--Person

     1 package com.spring.bean;
     2 
     3 public class Person {
     4     private Integer id;
     5     private String username;
     6     private String password;
     7     private String email;
     8     private int age;
     9     private Address address;
    10     
    11     public Person() {}
    12     public Person(String username, String password, String email, int agem,Address address) {
    13         super();
    14         this.username = username;
    15         this.password = password;
    16         this.email = email;
    17         this.age = age;
    18         this.address = address;
    19     }
    20     //不带address的构造函数
    21     public Person(String username, String password, String email, int age) {
    22         super();
    23         this.username = username;
    24         this.password = password;
    25         this.email = email;
    26         this.age = age;
    27     }
    28     //带id的构造函数
    29     public Person(Integer id,String username, String password, String email, int age) {
    30         super();
    31         this.id=id;
    32         this.username = username;
    33         this.password = password;
    34         this.email = email;
    35         this.age = age;
    36     }
    37     public String getUsername() {
    38         return username;
    39     }
    40     public void setUsername(String username) {
    41         this.username = username;
    42     }
    43     public String getPassword() {
    44         return password;
    45     }
    46     public void setPassword(String password) {
    47         this.password = password;
    48     }
    49     public String getEmail() {
    50         return email;
    51     }
    52     public void setEmail(String email) {
    53         this.email = email;
    54     }
    55     public int getAge() {
    56         return age;
    57     }
    58     public void setAge(int age) {
    59         this.age = age;
    60     }
    61     public Address getAddress() {
    62         return address;
    63     }
    64     public void setAddress(Address address) {
    65         this.address = address;
    66     }
    67     public Integer getId() {
    68         return id;
    69     }
    70     public void setId(Integer id) {
    71         this.id = id;
    72     }
    73     @Override
    74     public String toString() {
    75         return "Person [id=" + id + ", username=" + username + ", password=" + password + ", email=" + email + ", age="
    76                 + age + "]";
    77     }
    78     
    79     
    80 }

    2.insex

     1 <%@ page language="java" contentType="text/html; charset=utf-8"
     2     pageEncoding="utf-8"%>
     3 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
     4 <html>
     5 <head>
     6 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
     7 <title>Insert title here</title>
     8 </head>
     9 <body>
    10     <!-- 
    11         原始数据:1,tom,123456,tom@123.com,12
    12         要求:数据不能改变
    13         表单回显 id username password email age 
    14      -->
    15     <form action="helloworld9" method="post">
    16         <input type="hidden" name="id" value="1"/><br/><br>
    17         username:<input type="text" name="username" value="tom"/><br/><br>
    18         email:<input type="text" name="email" value="tom@123.com"/><br/><br>
    19         age:<input type="text" name="age" value="12"/><br/><br>
    20         <input type="submit" value="Submit">
    21     </form>
    22 </body>
    23 </html>

    3.controller

     1 package com.spring.it;
     2 
     3 import java.util.Map;
     4 
     5 import org.springframework.stereotype.Controller;
     6 import org.springframework.web.bind.annotation.ModelAttribute;
     7 import org.springframework.web.bind.annotation.RequestMapping;
     8 import org.springframework.web.bind.annotation.RequestParam;
     9 
    10 import com.spring.bean.Person;
    11 
    12 @Controller
    13 public class ModelAttributeControl {
    14     
    15     /**
    16      * 这是表单的post请求
    17      */
    18     @RequestMapping("/helloworld9")
    19     public String hello(Person person) {
    20         System.out.println("修改:"+person);
    21         return "success";
    22     }
    23     
    24     /**
    25      * 模拟从数据库中取得一个Person对象
    26      */
    27     @ModelAttribute
    28     public void getPerson(@RequestParam(value="id",required=false) Integer id,Map<String,Object> map) {
    29         if(id!=null) {
    30             //原始数据:1,tom,123456,tom@123.com,12
    31             Person person=new Person(1, "tom", "123456", "tom@123.com", 12);
    32             System.out.println("从数据库中获取一个数据:"+person);
    33             map.put("person", person);
    34         }
    35     }
    36 }

    4.效果

      

      其他的数据保持不变,主要看的数据是psaaword:

      

    三:会导致的异常

    1.异常

      通过源码的分析:

      在确定targer时,在implicitModel中查找attrName对象的属性值,若存在,则ok

      如果不存在,则验证当前是否使用了@SessionAttributes进行修饰,进行了修饰,则尝试从Session中获取值,若session中没有attrName对应的属性值,则跑出异常。

      若没有使用@SessionAttributes进行修饰,或者@SessionAttributes没有使用键与attrName匹配,则通过反射创建POJO对象。

    2.SpringMVC确定目标方法POJO入参

      1.确定一个 key:
        1). 若目标方法的 POJO 类型的参数木有使用 @ModelAttribute 作为修饰, 则 key 为 POJO 类名第一个字母的小写
        2). 若使用了 @ModelAttribute 来修饰, 则 key 为 @ModelAttribute 注解的 value 属性值.
      2. 在 implicitModel 中查找 key 对应的对象, 若存在, 则作为入参传入
        1). 若在 @ModelAttribute 标记的方法中在 Map 中保存过, 且 key 和 1 确定的 key 一致, 则会获取到.
      3. 若 implicitModel 中不存在 key 对应的对象, 则检查当前的 Handler 是否使用 @SessionAttributes 注解修饰,
         若使用了该注解, 且 @SessionAttributes 注解的 value 属性值中包含了 key, 则会从 HttpSession 中来获取 key 所
        对应的 value 值, 若存在则直接传入到目标方法的入参中. 若不存在则将抛出异常.
      4. 若 Handler 没有标识 @SessionAttributes 注解或 @SessionAttributes 注解的 value 值中不包含 key, 则
         会通过反射来创建 POJO 类型的参数, 传入为目标方法的参数
      5. SpringMVC 会把 key 和 POJO 类型的对象保存到 implicitModel 中, 进而会保存到 request 中.

    四:ModelAttribute注解修饰POJO类型的入参

    1.程序实例

     1   @ModelAttribute
     2     public void getUser(@RequestParam(value="id",required=false) Integer id, 
     3             Map<String, Object> map){
     4         System.out.println("modelAttribute method");
     5         if(id != null){
     6             //模拟从数据库中获取对象
     7             User user = new User(1, "Tom", "123456", "tom@atguigu.com", 12);
     8             System.out.println("从数据库中获取一个对象: " + user);
     9             
    10             map.put("abc", user);
    11         }
    12     }
    13     
    14     @RequestMapping("/testModelAttribute")
    15     public String testModelAttribute(@ModelAttribute("abc") User user){
    16         System.out.println("修改: " + user);
    17         return SUCCESS;
    18     }

    2.解释

      上面的put中放入的key是abc,所以需要在使用user的地方进行ModelAttribute注解。

      如果是默认的情况下,就是说不使用注解,就需要使用默认的key,将第一个字母小写后的类名。

  • 相关阅读:
    DOM元素的位置、尺寸及更多的信息
    BASE1(matlab)
    安装 sublime package control
    php 排序
    highstock
    html5 压缩图片 上传
    2016012016+小学四则运算练习软件项目报告
    构建之法初次阅读之1,2,16章
    一段异步操作的代码(清理缓存)
    计算两点距离 ios
  • 原文地址:https://www.cnblogs.com/juncaoit/p/8460119.html
Copyright © 2020-2023  润新知