@ModelAttribute有三种用法:
- 可以标注在方法上;
- 可以标注在方法中的参数上;
- 还可以和@RequestMapping一起标注在方法上;
三种方式各不一样,下面分别演示
一、@ModelAttribute标注在方法上
@ModelAttribute标注的方法会在Controller类的每个映射url的控制执行方法之前执行。
1、@ModelAttribute标注的方法返回空值
创建控制视图类:
@Controller
public class MyModelAttribute {
/*Model为模型,表示把数据放在返回的视图页面上*/
@ModelAttribute
public void testModeelAttribute(Model model){
model.addAttribute("username", "lzj");
}
@RequestMapping("/hello")
public String hello(){
return "hello";
}
}
在src/main/resources/templates目录下创建视图模板hello.ftl:
<h1>This is Hello Page</h1>
<p>username: ${username}</p>
运行工程,在浏览器中输入http://localhost:8080/hello后,控制视图方法hello()响应该请求,但在执行hello()方法之前先要执行@ModelAttribute标注的testModeelAttribute()方法。
2、@ModelAttribute标注的方法响应带输入参数的请求
@Controller
public class MyModelAttribute {
@ModelAttribute
public void testModeelAttribute(@RequestParam("name") String name1, Model model){
model.addAttribute("username", name1);
}
@RequestMapping("/hello")
public String hello(){
return "hello";
}
}
比如浏览器中输入http://localhost:8080/hello?name=lzj后,由控制视图类中的hello()方法来执行请求,在执行请求之前先执行testModeelAttribute()方法。由于请求中传入了name参数,testModeelAttribute()中先通过@RequestParam("name") String name1
把请求参数的name值放在程序中的name1变量中。也可以像下面这样写
public void testModeelAttribute(String name, Model model)
这样就不需要@RequestParam注解,但是String name的定义的name变量名就要与请求中name名保持一致。
3、@ModelAttribute标注的方法返回对象
控制视图类:
@Controller
public class MyModelAttribute {
@ModelAttribute
/*1.把请求链接中的name属性的值赋给username变量,请求链接中的age属性赋给age变量;
2.返回类型为对象,相当于把返回的对象放到了请求模型中,返回的对象相当于模型中的值,键相当于@ModelAttribute注解标注的方法的首字母小写,即testModeelAttribute;
即model.addAttribute("testModeelAttribute", user);
*/
public User testModeelAttribute(@RequestParam("name") String username, @RequestParam("age") Integer age){
User user = new User();
user.setUsername(username);
user.setAge(age);
return user;
}
@RequestMapping("/user")
/*模型中已经放入属性和值,model.addAttribute("testModeelAttribute", user);然后通过@ModelAttribute("testModeelAttribute")标注在属性上,表示把模型中的testModeelAttribute键对应的value值赋给了usr。*/
public String User(@ModelAttribute("testModeelAttribute") User usr, Model model){
model.addAttribute("user", usr);
return "user";
}
}
User类为:
public class User {
private String username;
private int age;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User [username=" + username + ", age=" + age + "]";
}
}
user.ftl视图模板为:
<h1>This is User Page</h1>
<p>user: ${user}</p>
启动spring boot工程,在浏览器中输入http://localhost:8080/user?name=lzj&age=20,控制视图方法响应请求前,先执行@ModelAttribute注解标注的testModeelAttribute方法,该方法把testModeelAttribute键对应的值user放到视图中,在user()响应方法中获取模型中testModeelAttribute对应的值,然后又放到了视图中。
4、@ModelAttribute标注方法时,指定放在模型中的键值
在上面一个例子中,@ModelAttribute标注的testModeelAttribute()方法默认把键为testModeelAttribute,value值为user的键值对放在了model模型中。但是我们可以显示指定放在模型中的键的名字。
/*相当于把model.addAttribute("userAttribute", user)放在了请求模型中*/
@ModelAttribute("userAttribute")
public User testModeelAttribute(@RequestParam("name") String username, @RequestParam("age") Integer age){
User user = new User();
user.setUsername(username);
user.setAge(age);
return user;
}
@RequestMapping("/user")
/*把请求模型中userAttribute键对应的值赋给usr变量中*/
public String User(@ModelAttribute("userAttribute") User usr, Model model){
usr.setAge(25);
model.addAttribute("user", usr);
return "user";
}
二、@ModelAttribute标注在方法的参数上
当@ModelAttribute属性标识在方法的参数上时,表示从请求域的模型中读取属性。例如
@Controller
public class MyModelAttribute {
@ModelAttribute("name")
public void regNameModeelAttribute(Model model){
model.addAttribute("name", "lzj");
}
@ModelAttribute
public void regAgeModeelAttribute(Model model){
/*把键值属性放到请求模型中*/
model.addAttribute("age", "20");
}
@RequestMapping("/reg")
/*@ModelAttribute标识在参数的前面,表示从请求模型的中读取键值为name的属性的value值放在username中*/
public String reg(@ModelAttribute("name") String username, @ModelAttribute("age") String age){
System.out.println("name:" + username + "; age:" + Integer.valueOf(age));
return "reg";
}
}
启动工程,在浏览器中输入http://localhost:8080/reg后,控制视图方法reg()响应请求前,先执行regNameModeelAttribute()和regAgeModeelAttribute()方法,最后后台输出:name:lzj; age:20
三、@ModelAttribute和@RequestMapping同时标注在同一个方法上
当两个注解同时标注在一个方法上时,该方法返回的内容不再被视图解析器解析为视图了,而是把放回的内容放到模型的属性中,视图还是继续返回@RequestMapping映射的那个视图。
@Controller
public class MyModelAttribute {
@RequestMapping("/login")
@ModelAttribute("name")
public String login(@RequestParam(value="username", required=false) String username){
System.out.println("--username-- : " + username);
return username;
}
}
当login()方法响应请求后,执行方法,然后把方法的返回值username放到请求模型的name属性中,相当于model.addAttribute("name", username)
。当请求方法执行完后,会把请求的url继续返回到浏览器。
login.ftl模板视图:
<h1>This is Login Page</h1>
<p>name: ${name}</p>
启动工程,在浏览器中输入http://localhost:8080/login?username=lzj后,login()方法响应后,显示login.ftl网页。