• @ModelAttribute注解和POJO传参过程


    1、@ModelAttribute注解

    @ModelAttribute主要有三个用途,对方法进行注解,对参数进行注解,还有@ModelAttribute和@RequestMapping一起对方法进行注解。

    (1) 对方法进行注解

    @ModelAttribute对方法进行注解,有两个作用,一是在调用@RequestMapping注解的方法之前,先调用@ModelAttribute注解的方法,二是在@ModelAttribute注解的方法中,所有Map的对象都放入ImpliciteModel中,key就是Map的key。在后面讲解POJO传参的过程中,会讲解ImpliciteModel的作用。测试代码如下:

    两个POJO代码如下:、

    User.java

     1 package com.hxg.springmvc.entries;
     2 
     3 public class User {
     4     private String username;
     5     private String password;
     6     private int id;
     7 
     8     public int getId() {
     9         return id;
    10     }
    11 
    12     @Override
    13     public String toString() {
    14         return "User [username=" + username + ", password=" + password
    15                 + ", id=" + id + "]";
    16     }
    17 
    18     public void setId(int id) {
    19         this.id = id;
    20     }
    21 
    22     public String getUsername() {
    23         return username;
    24     }
    25 
    26     public void setUsername(String username) {
    27         this.username = username;
    28     }
    29 
    30     public String getPassword() {
    31         return password;
    32     }
    33 
    34     public void setPassword(String password) {
    35         this.password = password;
    36     }
    37 
    38     public User(int id, String username, String password) {
    39         super();
    40         this.username = username;
    41         this.password = password;
    42         this.id = id;
    43     }
    44 
    45     public User() {
    46         super();
    47     }
    48 
    49 }
    View Code

    Cat.java

     1 package com.hxg.springmvc.entries;
     2 
     3 public class Cat {
     4     private int speed;
     5 
     6     public int getSpeed() {
     7         return speed;
     8     }
     9 
    10     public void setSpeed(int speed) {
    11         this.speed = speed;
    12     }
    13 
    14 }
    View Code

    Controller的代码如下

     1 package com.hxg.springmvc.web.controller;
     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.SessionAttributes;
     9 
    10 import com.hxg.springmvc.entries.Cat;
    11 import com.hxg.springmvc.entries.User;
    12 
    13 @Controller
    14 public class HandlerController {
    15     
    16     @RequestMapping("/hello")
    17     public String hello(@ModelAttribute("users")User user, Map<String, Object> map, Cat cat, String password)
    18     {
    19         cat.setSpeed(100);
    20         System.out.println(password);
    21         return "hello";
    22     }
    23     
    24     @ModelAttribute
    25     public String preUser(Cat cat, User user, Map<String, Object> map, String username)
    26     {
    27         System.out.println(username);
    28         cat.setSpeed(110);
    29         user.setId(1);
    30         User user1 = new User(2, "username1", "password1");
    31         map.put("users", user1);
    32         return "abc";
    33     }
    34     
    35     
    36     
    37 }
    View Code

    提交表单的部分代码

    1 <form action="hello.do" method="post">
    2     <input name="username" type="text"/>
    3     <input name="password" type="text"/>
    4     <input type="submit" value="submit" > 
    5 </form>
    View Code

    页面显示代码:

     1 <body>
     2 user:
     3 ${user.username }
     4 ${user.password }
     5 ${user.id }
     6 <br><br>
     7 users:
     8 ${users.username }
     9 ${users.password }
    10 ${users.id }
    11 <br><br>
    12 string:
    13 ${string}
    14 <br><br>
    15 cat:
    16 ${cat.speed }
    17 <br><br>
    18 username:
    19 ${username }
    20 <br><br>
    21 password:
    22 ${password }
    23 </body>
    View Code

    在表单中输入username, password,页面显示的结果如下:

    控制台中输出:username  password

    从结果可以看出:@ModelAttribute注解的方法在@RequestMapping注解的方法之前执行,并且preUser方法中,一共有四个对象放入map中,相当于:

    map.put("cat", cat)、map.put("user", user)、map.put("users", user1)和map.put("string", "abc");

    POJO在传参的过程中,springmvc会默认的把POJO放入到map中,其中键值就是类名的第一个字母小写。在@ModelAttribute注解的方法里,POJO放入到Map的同时,也放入ImpliciteModel中, 比如上面代码中的user和cat。@ModelAttribute注解的方法里,返回类型不是void,则返回的值也会被放到Map中,其中键值为返回类型的第一个字母小写。比如上述代码中,返回的"abc",就会被放入到Map中,相当于map.put("string", "abc")。

      在执行@ModelAttribute注解的方法里,表单的数据会被当作参数传到@ModelAttribute注解的方法,和@RequestMapping注解的方法传参是一样的。

    (2) @ModelAttribute对参数进行注解

    比如上面的代码,@ModelAttribute("users")User user。在传参的过程中,首先检查ImpliciteModel有没有键值为users,有的话,直接从ImpliciteModel中取出该对象,然后在把表单传过来的数据赋值到该对象中,最后把该对象当作参数传入到@RequestMapping注解方法里,也就是hello方法。当检查到键值的话,并不会创建新的对象,而是直接从ImpliciteModel直接取出来。

    (3) @ModelAttribute和@RequestMapping一起对方法进行注解

    @ModelAttribute和@RequestMapping对方法进行注解时,其中返回类型被到Map中,并不会被当作视图的路径进行解析。把controller代码改变成如下:

     1 package com.hxg.springmvc.web.controller;
     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.SessionAttributes;
     9 
    10 import com.hxg.springmvc.entries.Cat;
    11 import com.hxg.springmvc.entries.User;
    12 
    13 @Controller
    14 public class HandlerController {
    15     
    16     @ModelAttribute
    17     @RequestMapping("/hello")
    18     public String hello(@ModelAttribute("users")User user, Map<String, Object> map, Cat cat, String password)
    19     {
    20         cat.setSpeed(100);
    21         System.out.println(password);
    22         return "bbbbb";
    23     }
    24     
    25     @ModelAttribute
    26     public String preUser(Cat cat, User user, Map<String, Object> map, String username)
    27     {
    28         System.out.println(username);
    29         cat.setSpeed(110);
    30         user.setId(1);
    31         User user1 = new User(2, "username1", "password1");
    32         map.put("users", user1);
    33         return "abc";
    34     }
    35     
    36     
    37     
    38 }
    View Code

    其中返回的视图路径就是@RequestMapping("/hello")中的hello,显示结果如下:

    从结果中,bac变为了bbbbb,主要是因为返回值会被放入到map,键值为返回类型第一个字母的小写,原来的map.put("string", "abc")被覆盖掉,变成map.put("string", "bbbbb")。

    2、POJO传参的过程

    POJO传参的过程中,先检查ImpliciteModel中是否有相对应的键值,有的话就把该键值的对象取出来,把表单传过来的数据传到该对象,然后把该对象作为参数传到目标方法中,也就是@RequestMapping注解的方法中。在ImpliciteModel没有相对应的键值,假如controller用SessionAttribute进行注解,则就会在Session attribute查找相对应的key,假如找到了key,却没有对象,则会报异常。在ImpliciteModel和SessionAttribute都没有查找到key,才会创建新的对象,把表单传过来的数据赋值给新的对象,最后把新的对象作为参数传到目标方法中。

    以下是报异常的代码

     1 package com.hxg.springmvc.web.controller;
     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.SessionAttributes;
     9 
    10 import com.hxg.springmvc.entries.Cat;
    11 import com.hxg.springmvc.entries.User;
    12 
    13 @SessionAttributes("user")
    14 @Controller
    15 public class HandlerController {
    16     
    17     @ModelAttribute
    18     @RequestMapping("/hello")
    19     public String hello(@ModelAttribute User user, Map<String, Object> map, Cat cat, String password)
    20     {
    21         cat.setSpeed(100);
    22         System.out.println(password);
    23         return "bbbbb";
    24     }
    25 }
    View Code

    会报如下异常:

     只要把@SessionAttributes("user")改成@SessionAttributes("users")就可以消去异常,或者把public String hello(@ModelAttribute User user, Map<String, Object> map, Cat cat, String password)中的@ModelAttribute 去掉,只有用@ModelAttribute注解参数,才会从session attribute中查找相对应的key。

  • 相关阅读:

    jQuery post使用变量作参数名
    线性结构____二叉堆
    Java虚拟机
    spring在线生成
    树形结构_红黑树:平衡2X 哈夫曼树:最优2X
    线性结构____双链表/栈/队列
    Java中的String,StringBuilder,StringBuffer三者的区别
    JPress的CMS系统在Window下的部署和使用
    List之contains方法
  • 原文地址:https://www.cnblogs.com/Hxinguan/p/6128774.html
Copyright © 2020-2023  润新知