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注解的使用方法有很多种,非常灵活,读者可以根据业务需求选择使用。