3.12 @ModelAttribute注解
用途:将请求参数绑定到对象
org.springframework.web.bind.annotation.ModelAttribute
注解用于将请求参数绑定到Model对象中。
属性
@ModelAttribute
注解只支持一个属性value
,类型为String
,表示绑定的属性名称。
注意
**提示:**被@ModelAttribute
注释的方法会在Controller
每个方法执行前被执行,因此在个Controlller
被映射到多个URL
时,要谨慎使用。
@ModelAttribute
注解的使用方式有很多种,下面来逐一介绍。
示例 @ModelAttribute注解的使用
项目结构
展开/折叠
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| G:\Desktop\随书源码\Spring+Mybatis企业应用实战(第2版)\codes\03\ModelAttributeTest ├─src\ │ └─org\ │ └─fkit\ │ ├─controller\ │ │ ├─FormController.java │ │ ├─ModelAttribute1Controller.java │ │ ├─ModelAttribute2Controller.java │ │ ├─ModelAttribute3Controller.java │ │ ├─ModelAttribute4Controller.java │ │ └─ModelAttribute5Controller.java │ └─domain\ │ └─User.java └─WebContent\ ├─index.jsp ├─META-INF\ │ └─MANIFEST.MF └─WEB-INF\ ├─content\ │ ├─login4.jsp │ ├─loginForm1.jsp │ ├─loginForm2.jsp │ ├─loginForm3.jsp │ ├─loginForm4.jsp │ ├─loginForm5.jsp │ ├─result1.jsp │ ├─result2.jsp │ ├─result3.jsp │ └─result5.jsp ├─lib\ │ ├─commons-logging-1.2.jar │ ├─spring-aop-5.0.1.RELEASE.jar │ ├─spring-aspects-5.0.1.RELEASE.jar │ ├─spring-beans-5.0.1.RELEASE.jar │ ├─spring-context-5.0.1.RELEASE.jar │ ├─spring-context-indexer-5.0.1.RELEASE.jar │ ├─spring-context-support-5.0.1.RELEASE.jar │ ├─spring-core-5.0.1.RELEASE.jar │ ├─spring-expression-5.0.1.RELEASE.jar │ ├─spring-instrument-5.0.1.RELEASE.jar │ ├─spring-jcl-5.0.1.RELEASE.jar │ ├─spring-jdbc-5.0.1.RELEASE.jar │ ├─spring-jms-5.0.1.RELEASE.jar │ ├─spring-messaging-5.0.1.RELEASE.jar │ ├─spring-orm-5.0.1.RELEASE.jar │ ├─spring-oxm-5.0.1.RELEASE.jar │ ├─spring-test-5.0.1.RELEASE.jar │ ├─spring-tx-5.0.1.RELEASE.jar │ ├─spring-web-5.0.1.RELEASE.jar │ ├─spring-webflux-5.0.1.RELEASE.jar │ ├─spring-webmvc-5.0.1.RELEASE.jar │ └─spring-websocket-5.0.1.RELEASE.jar ├─springmvc-config.xml └─web.xml
|
index.jsp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>测试@ModelAttribute</title> </head> <body> <h3>测试@ModelAttribute的不同用法</h3> <a href="loginForm1">测试@ModelAttribute(value="")注释返回具体类的方法 </a> <br> <a href="loginForm2">测试@ModelAttribute注释的返回值为void的方法</a> <br> <a href="loginForm3">测试@ModelAttribute注释的返回值为具体类的方法</a> <br> <a href="loginForm4">测试@ModelAttribute和@RequestMapping同时注释一个方法的情况</a> <br> <a href="loginForm5">测试@ModelAttribute注释一个方法的参数 </a> <br> </body> </html>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| package org.fkit.controller;
import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping;
@Controller public class FormController { @RequestMapping(value = "/{formName}") public String loginForm(@PathVariable String formName) { return formName; } }
|
1.测试@ModelAttribute(value=””)注释返回具体类的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>测试@ModelAttribute</title> </head> <body> <h3>测试@ModelAttribute(value="")注释返回具体类的方法</h3> <form action="login1" method="post"> <table> <tr> <td><label>登录名: </label></td> <td><input type="text" id="loginname" name="loginname"></td> </tr> <tr> <td><input id="submit" type="submit" value="登录"></td> </tr> </table> </form> </body> </html>
|
ModelAttribute1Controller.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| package org.fkit.controller;
import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam;
@Controller public class ModelAttribute1Controller { @ModelAttribute("loginname") public String (@RequestParam("loginname") String loginname) { return loginname; } @RequestMapping(value = "/login1") public String login1() { return "result1"; } }
|
在ModelAttributelController
类中除了@RequestMapping
映射的login1
方法之外,还提供了一个userModel1
方法,该方法上有一个@ModelAttribute
注解。此处@ModelAttribute
注解默认的value
值为“loginname”
,用来指定model
属性的名称,而model
属性的值就是userModel1
方法的返回值。被@ModelAttribute
注解的userMode11
方法会先于login1
调用,它把请求参数loginname
的值赋给userModel1
方法的形式参数loginname
,并设置了一个属性loginname
到Model
当中,而属性的值就是方法的形式参数loginame
的值。
result1.jsp
1 2 3 4 5 6 7 8 9 10 11 12 13
| <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>测试@ModelAttribute(value="")注释返回具体类的方法</title> </head> <body> 访问request作用范围域中的loginname对象:${requestScope.loginname } <br> </body> </html>
|
在跳转的result1.jsp
中可以访问到由@ModelAttribute
设置在Model
中的的loginname
的值。
测试
部署ModelAttributeTest
这个Web
应用,在浏览器中输入如下URL
来测试应用:
1
| http://localhost:8080/ModelAttributeTest/index.jsp
|
单击”测试@ModelAttribute(value="")注释返回具体类的方法
“超链接发送请求,跳转到loginForm1.jsp
页面.
输入登录名"test"
,单击”登录
“按钮发送请求,而后将先调用userMode1
方法,再调用login1
方法并跳转到result1.jsp
页面。
可以看到,在request
作用域中访问到了Model
的值。
2.测试@ModelAttribute注释void返回值的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>测试@ModelAttribute</title> </head> <body> <h3>测试@ModelAttribute注释void返回值的方法</h3> <form action="login2" method="post"> <table> <tr> <td><label>登录名: </label></td> <td><input type="text" id="loginname" name="loginname"></td> </tr> <tr> <td><label>密码: </label></td> <td><input type="password" id="password" name="password"></td> </tr> <tr> <td><input id="submit" type="submit" value="登录"></td> </tr> </table> </form> </body> </html>
|
ModelAttribute2Controller.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| package org.fkit.controller;
import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam;
@Controller public class ModelAttribute2Controller { @ModelAttribute public void userModel2(@RequestParam("loginname") String loginname, @RequestParam("password") String password, Model model) { model.addAttribute("loginname", loginname); model.addAttribute("password", password); } @RequestMapping(value = "/login2") public String login2() { return "result2"; } }
|
在ModelAttribute2Controller
类中除了@RequestMapping
映射的login2
方法之外,还提供了一个userModel2
方法,该方法上有一个@ModelAttribute
注解。 userMode12
方法会先于login
方法被调用,它把请求参数值赋给对应变量,model
属性名称和值由model.addAttribute()
方法实现,前提是要在方法中加入一个Model
类型的参数。
result2.jsp
1 2 3 4 5 6 7 8 9 10 11 12 13
| <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>测试@ModelAttribute注释void返回值的方法</title> </head> <body> 访问request作用范围域中的loginname对象:${requestScope.loginname } <br> 访问request作用范围域中的password对象:${requestScope.password } </body> </html>
|
在跳转的result2.jsp
中可以访问到由@ModelAttribute
注解设置的loginname
和password
的值.
测试
在浏览器中输入如下URL
来测试应用
1
| http://localhost:8080/ModelAttributeTest/index.jsp
|
单击“测试@ModelAttribute注释void返回值的方法
”超链接发送请求,将会跳转到loginForm2.jsp
页面。
输入登录名"test"
,密码“123456
”,单击“登录”按钮发送请求,而后将先调用userModel2
方法,再调用login2
方法,并跳转到result2.jsp
页面.
可以看到,在request
作用域中访问到了Model
的值。
3.测试@ModelAttribute注释返回具体类的方法
ModelAttribute3Controller.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| package org.fkit.controller;
import java.util.ArrayList; import java.util.List; import org.fkit.domain.User; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam;
@Controller public class ModelAttribute3Controller { private static List<User> userList; public ModelAttribute3Controller() { super(); userList = new ArrayList<User>(); User user1 = new User("test", "123456", "测试用户"); User user2 = new User("admin", "123456", "管理员"); userList.add(user1); userList.add(user2); } public User find(String loginname, String password) { for (User user : userList) { if (user.getLoginname().equals(loginname) && user.getPassword().equals(password)) { return user; } } return null; } @ModelAttribute public User userModel3(@RequestParam("loginname") String loginname, @RequestParam("password") String password) { return find(loginname, password); } @RequestMapping(value = "/login3") public String login3() { return "result3"; } }
|
在ModelAttribute3Controller
类中除了@RequestMapping
映射的login3
方法之外,还提供了一个userModel3
方法,该方法上有一个@ModelAttribute
注解。 userModel3
方法会先于login3
方法被调用,这里model
属性的名称没有被指定,它由@ModelAttribute
注解的userModel3
方法的返回类型隐含表示,如这个方法返回User
类型,那么这个model
属性的名称就是user
。此处find(loginname, password)
方法用来模拟数据库根据登录名和密码查询用户的功能实现。
result3.jsp
1 2 3 4 5 6 7 8 9 10 11 12 13
| <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>测试@ModelAttribute注释返回具体类的方法</title> </head> <body> 访问request作用范围域中的user对象:${requestScope.user.username } <br> </body> </html>
|
在跳转的result2.jsp
页面中可以访问到由@ModelAttribute
设置的loginname
和password
的值。
测试
在浏览器中输入如下URL
来测试应用
1
| http://localhost:8080/ModelAttributeTest/index.jsp
|
单击”测试@ModelAttribute注释返回具体类的方法
“超链接发送请求,将跳转到lσginForm3.jsp
页面,
输入登录名"test"
,密码"123456"
,单击”登录”按钮发送请求,而后将先调用userModel3
方法,再调用login3
方法,并跳转到result3.jsp
页面.
可以看到,在request
作用域中访问到了User
对象。
4 测试ModelAttribute和@RequestMapping同时注释一个方法
ModelAttribute4Controller.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| package org.fkit.controller;
import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping;
@Controller public class ModelAttribute4Controller { @RequestMapping(value = "/login4") @ModelAttribute(value = "username") public String login4() { return "admin"; } }
|
在ModelAttribute4Controller
中,@ModelAttribute
和@RequestMapping
同时注释一个方法,此时
login4
方法的返回值并不是一个视图名称,而是model
属性的值,视图名称是@RequestMapping
的value
值"/login4"
,Model
的属性名称由@ModelAttribute
的value
值指定,这相当于在request
中封装了username(key)= admin(value)
。
- 注意,
- 此处
login4
方法跳转的结果是"/login4"
。
login4.jsp
1 2 3 4 5 6 7 8 9 10 11 12 13
| <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>测试@ModelAttribute和@RequestMapping同时注释一个方法</title> </head> <body> 访问request作用范围域中的username对象:${requestScope.username } <br> </body> </html>
|
测试
在浏览器中输入如下URL
来测试应用
1
| http://localhost:8080/ModelAttributeTest/index.jsp
|
- 单击“
测试@ModelAttribute和@RequestMapping同时注释一个方法
”超链接发送请求,而后跳转到loginForm4.jsp
页面
- 输入登录名
“test”
,密码“123456”
,单击”登录”按钮发送请求,将调用login4
方法,跳转到login4.jsp
页面,如图3.18所示。
- 可以看到,在
request
作用域中访问到了username
的值,也就是login4
方法的返回值"admin"
。
5 测试@ModelAttribute注释一个方法的参数
ModelAttribute5Controller.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| package org.fkit.controller;
import org.fkit.domain.User; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping;
@Controller public class ModelAttribute5Controller { @RequestMapping(value = "/login5") public String login5(@ModelAttribute User user) { user.setUsername("管理员"); return "result5"; } }
|
ModelAttribute5Controller
类中login5
方法的参数User
使用了@ModelAttribute
注解,前台页面的控件的值会自动入参到@ModelAttribute
注解修饰的对象 的同名属性当中。这种方式是在实际开发中使用最多的方式。
result5.jsp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>测试@ModelAttribute注释一个方法的参数</title> </head> <body> 访问request作用范围域中的user对象的loginname属性:${requestScope.user.loginname } <br> 访问request作用范围域中的user对象的password属性:${requestScope.user.password } <br> 访问request作用范围域中的user对象的username属性:${requestScope.user.username } <br> </body> </html>
|
测试
在浏览器中输入如下URL
来测试应用
1
| http://localhost:8080/ModelAttributeTest/index.jsp
|
单击测试@ModelAttribute注释一个方法的参数
超链接发送请求,跳转到loginForm5.jsp
页面.输入登录名test
,密码123456
,单击登录按钮发送请求,而后将调用login5
方法,跳转到result5.jsp
页面.
可以看到,在request
作用域中访问到了User
对象.
提示@ModeAttribute
注解的使用方法有很多种,非常灵活,读者可以根据业务需求选择使用。