@ModelAttribute(被此注解标记的方法不妨称之为预处理方法):预处理方法在请求方法之前执行,类似于"大内总管"(请求要见皇上,先通过大内总管)。先执行【预处理方法】,再执行【请求方法】(对应请求路径下的方法)。
@ModelAttribute既可以作用在预处理方法上,也可以作用在请求方法参数上。预处理方法可以有返回值,也可以无返回值。
先给出User类的成员列表,方便后面讲解:
@ModelAttribute有两个作用:从请求中获取值(往往会进行预处理);给请求方法传值(往往是预处理结果)。
一、从请求中获取值(往往会进行预处理)
二、给请求方法传值(往往是预处理结果)
1、预处理方法通过返回值给请求方法传值:
这里贴一个不能传值的例子:
其对应的输出为:
2、预处理方法通过Map参数给请求方法传值:
看到这里,读者可能已经发现:请求和预处理方法都可以给请求方法传值!
这两种方式会不会有冲突呢?比如【请求】给【请求方法】传了一个name,【预处理方法】也给【请求方法】传了一个name,这时候会怎么样呢?
上面beforeTest2给test2传了一个User对象,假设为user1{name=haha, age=20},表单也会给test2传一个User对象,假设为user2{name=Tom}(假设name输入框输入了Tom;表单中没有age)。在这种情况下,请求方法得到的User对象最终是什么呢?
答案是:
根据答案得到的结论:当请求和预处理方法给请求方法传了相同类型的对象时,合并之;若有冲突,以请求的为准!
@ModelAttribute有两种用法:只作用在预处理方法上;同时作用在请求方法的参数和预处理方法上。
一、只作用在预处理方法上
1、无返回值:
2、有返回值:
二、同时作用在请求方法的参数和预处理方法上
1、预处理方法有返回值:
2、预处理方法无返回值:
简单总结一下:
最后附上源码:
项目结构:
pom.xml的内容:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>P050_ModelAttribute</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <name>P050_ModelAttribute Maven Webapp</name> <!-- FIXME change it to the project's website --> <url>http://www.example.com</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.7</maven.compiler.source> <maven.compiler.target>1.7</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.1.8.RELEASE</version> </dependency> </dependencies> <build> <finalName>P050_ModelAttribute</finalName> <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) --> <plugins> <plugin> <artifactId>maven-clean-plugin</artifactId> <version>3.1.0</version> </plugin> <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging --> <plugin> <artifactId>maven-resources-plugin</artifactId> <version>3.0.2</version> </plugin> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.0</version> </plugin> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.22.1</version> </plugin> <plugin> <artifactId>maven-war-plugin</artifactId> <version>3.2.2</version> </plugin> <plugin> <artifactId>maven-install-plugin</artifactId> <version>2.5.2</version> </plugin> <plugin> <artifactId>maven-deploy-plugin</artifactId> <version>2.8.2</version> </plugin> </plugins> </pluginManagement> </build> </project>
web.xml的内容:
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" > <web-app> <display-name>Archetype Created Web Application</display-name> <servlet> <servlet-name>dispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!--关联springmvc.xml,让其中的配置生效!--> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>dispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
springmvc.xml的内容:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <!--开启对Spring MVC注解的支持--> <mvc:component-scan base-package="cn.liuxingchang.controller"></mvc:component-scan> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="viewResolver"> <property name="prefix" value="/WEB-INF/pages/"></property> <property name="suffix" value=".jsp"></property> </bean> </beans>
User.java的内容:
package cn.liuxingchang.domain; public class User { private String name; private Integer age; @Override public String toString() { return "User{" + "name='" + name + '\'' + ", age=" + age + '}'; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } }
index.jsp的内容:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <body> <h3>test:预处理方法(有返回值)给请求方法传值</h3> <h3>从请求中获取值</h3> <a href="test?name=Tom">test</a> <br /><br /> <%----------------------%> <h3>test2:预处理方法(有返回值)给请求方法传值</h3> <form method="post" action="test2"> name: <input type="text" name="name" /><br /> <input type="submit" /> </form> <br /><br /> <%----------------------%> <h3>test3:预处理方法(有返回值)给请求方法传值2</h3> <form method="post" action="test3"> name: <input type="text" name="name" /><br /> <input type="submit" /> </form> <br /><br /> <%----------------------%> <h3>test4:预处理方法(无返回值)给请求方法传值</h3> <form method="post" action="test4"> name: <input type="text" name="name" /><br /> <input type="submit" /> </form> <br /><br /> <%----------------------%> <h3>test5:预处理方法(无返回值)给请求方法传值2</h3> <form method="post" action="test5"> name: <input type="text" name="name" /><br /> <input type="submit" /> </form> <br /><br /> <%----------------------%> <h3>test6:预处理方法(无返回值)给请求方法传值2</h3> <form method="post" action="test6"> name: <input type="text" name="name" /><br /> <input type="submit" /> </form> <br /><br /> </body> </html>
success.jsp的内容:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <h3>Success!</h3> </body> </html>
Test.java的内容:
package cn.liuxingchang.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class Test { @RequestMapping("/test") public String test(String name) { System.out.println(name); return "success"; } @ModelAttribute public void beforeTest(String name) { System.out.println(name); } }
Test2.java的内容:
package cn.liuxingchang.controller; import cn.liuxingchang.domain.User; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class Test2 { @RequestMapping("/test2") public String test2(User user) { System.out.println(user); return "success"; } @ModelAttribute public User beforeTest2(String name) { User user = new User(); user.setName("haha"); //此句会被请求参数覆盖 user.setAge(20); return user; } }
Test3.java的内容(这里预处理方法给请求方法传不了值):
package cn.liuxingchang.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class Test3 { @RequestMapping("/test3") public String test3(Integer age, String name) { System.out.println(age); System.out.println(name); return "success"; } @ModelAttribute public Integer beforeTest3() { Integer age = 20; return age; } }
Test4.java的内容:
package cn.liuxingchang.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import java.util.Map; @Controller public class Test4 { @RequestMapping("/test4") public String test4(@ModelAttribute("gift") String gift, String name) { System.out.println(gift); System.out.println(name); return "success"; } @ModelAttribute public void beforeTest4(Map<String, String> map) { map.put("gift", "Benz"); } }
Test5.java的内容:
package cn.liuxingchang.controller; import cn.liuxingchang.domain.User; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import java.util.Map; @Controller public class Test5 { @RequestMapping("/test5") public String test5(@ModelAttribute("gift") String gift, @ModelAttribute("user") User user) { System.out.println(gift); System.out.println(user); return "success"; } @ModelAttribute public void beforeTest5(Map<String, Object> map) { map.put("gift", "Benz"); User user = new User(); user.setAge(100); map.put("user", user); } }
Test6.java的内容:
package cn.liuxingchang.controller; import cn.liuxingchang.domain.User; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import java.util.Map; @Controller public class Test6 { @RequestMapping("/test6") public String test6(@ModelAttribute("gift") String gift, User user) { System.out.println(gift); System.out.println(user); return "success"; } @ModelAttribute public User beforeTest6(Map<String, String> map) { map.put("gift", "Benz"); User user = new User(); user.setAge(100); return user; } }