@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。

原文地址:https://www.cnblogs.com/Hxinguan/p/6128774.html