@ModelAttribute注解和POJO传参过程
1、@ModelAttribute注解
@ModelAttribute主要有三个用途,对方法进行注解,对参数进行注解,还有@ModelAttribute和@RequestMapping一起对方法进行注解。
(1) 对方法进行注解
@ModelAttribute对方法进行注解,有两个作用,一是在调用@RequestMapping注解的方法之前,先调用@ModelAttribute注解的方法,二是在@ModelAttribute注解的方法中,所有Map的对象都放入ImpliciteModel中,key就是Map的key。在后面讲解POJO传参的过程中,会讲解ImpliciteModel的作用。测试代码如下:
两个POJO代码如下:、
User.java
package com.hxg.springmvc.entries;
public class User {
private String username;
private String password;
private int id;
public int getId() {
return id;
}
@Override
public String toString() {
return "User [username=" + username + ", password=" + password
+ ", id=" + id + "]";
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public User(int id, String username, String password) {
super();
this.username = username;
this.password = password;
this.id = id;
}
public User() {
super();
}
}
Cat.java
package com.hxg.springmvc.entries;
public class Cat {
private int speed;
public int getSpeed() {
return speed;
}
public void setSpeed(int speed) {
this.speed = speed;
}
}
Controller的代码如下
package com.hxg.springmvc.web.controller; import java.util.Map; 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.SessionAttributes; import com.hxg.springmvc.entries.Cat;
import com.hxg.springmvc.entries.User; @Controller
public class HandlerController { @RequestMapping("/hello")
public String hello(@ModelAttribute("users")User user, Map<String, Object> map, Cat cat, String password)
{
cat.setSpeed(100);
System.out.println(password);
return "hello";
} @ModelAttribute
public String preUser(Cat cat, User user, Map<String, Object> map, String username)
{
System.out.println(username);
cat.setSpeed(110);
user.setId(1);
User user1 = new User(2, "username1", "password1");
map.put("users", user1);
return "abc";
} }
提交表单的部分代码
<form action="hello.do" method="post">
<input name="username" type="text"/>
<input name="password" type="text"/>
<input type="submit" value="submit" >
</form>
页面显示代码:
<body>
user:
${user.username }
${user.password }
${user.id }
<br><br>
users:
${users.username }
${users.password }
${users.id }
<br><br>
string:
${string}
<br><br>
cat:
${cat.speed }
<br><br>
username:
${username }
<br><br>
password:
${password }
</body>
在表单中输入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代码改变成如下:
package com.hxg.springmvc.web.controller; import java.util.Map; 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.SessionAttributes; import com.hxg.springmvc.entries.Cat;
import com.hxg.springmvc.entries.User; @Controller
public class HandlerController { @ModelAttribute
@RequestMapping("/hello")
public String hello(@ModelAttribute("users")User user, Map<String, Object> map, Cat cat, String password)
{
cat.setSpeed(100);
System.out.println(password);
return "bbbbb";
} @ModelAttribute
public String preUser(Cat cat, User user, Map<String, Object> map, String username)
{
System.out.println(username);
cat.setSpeed(110);
user.setId(1);
User user1 = new User(2, "username1", "password1");
map.put("users", user1);
return "abc";
} }
其中返回的视图路径就是@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,才会创建新的对象,把表单传过来的数据赋值给新的对象,最后把新的对象作为参数传到目标方法中。
以下是报异常的代码
package com.hxg.springmvc.web.controller; import java.util.Map; 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.SessionAttributes; import com.hxg.springmvc.entries.Cat;
import com.hxg.springmvc.entries.User; @SessionAttributes("user")
@Controller
public class HandlerController { @ModelAttribute
@RequestMapping("/hello")
public String hello(@ModelAttribute User user, Map<String, Object> map, Cat cat, String password)
{
cat.setSpeed(100);
System.out.println(password);
return "bbbbb";
}
}
会报如下异常:

只要把@SessionAttributes("user")改成@SessionAttributes("users")就可以消去异常,或者把public String hello(@ModelAttribute User user, Map<String, Object> map, Cat cat, String password)中的@ModelAttribute 去掉,只有用@ModelAttribute注解参数,才会从session attribute中查找相对应的key。
@ModelAttribute注解和POJO传参过程的更多相关文章
- @ModelAttribute 注解及 POJO入参过程
一.modelattribute注解 @ModelAttribute注解的方法有两种,一种无返回值,一种有返回值,方法的可以用@RequestParam注解来获取请求的参数,如果不获取参数,可以不用此 ...
- C/C++函数调用时传参过程与可变参数实现原理
C/C++函数调用时传参过程与可变参数实现原理 C语言的经典swap问题 在学习C语言的时候,我们大都遇到过一些经典例题,这些经典例题背后所代表的是往往是C/C++背后的一些运行原理,比如下面这个示例 ...
- Spring MVC POJO传参方式
有两POJO类 Address.java package com.proc; public class Address { private String province; private Strin ...
- SpringMVC POJO传参方式
有两POJO类 Address.java package com.proc; public class Address { private String province; private Strin ...
- url传参过程中文字需编码、解码使用
1.链接进行编码跳转:window.location.href = encodeURI(url) 2.获取当前链接进行解码:decodeURI(window.location); 3.获取url中参数 ...
- 7、SpringMVC源码分析(2):分析HandlerAdapter.handle方法,了解handler方法的调用细节以及@ModelAttribute注解
从上一篇 SpringMVC源码分析(1) 中我们了解到在DispatcherServlet.doDispatch方法中会通过 mv = ha.handle(processedRequest, res ...
- 关于url传参中文乱码问题
之前都一直很不了解中文编码得问题,之前在做项目中没碰到那么头痛的问题.所以一直没有了解中文乱码的问题. 问题描述: 地址: http://localhost:8080/sun-government/c ...
- 学习笔记:JavaScript传参方式———ECMAScript中所有函数的参数都是按值传递
我们把命名参数(arguments)视为局部变量,在向参数传递基本类型值时,如同基本类型变量的复制一样,传递一个副本,参数在函数内部的改变不会影响外部的基本类型值.如: function add10( ...
- (1)构造方法和方法重载 (2)this关键字 (3)方法的传参和递归调用
1.构造方法和方法重载如: Person p = new Person(); - 声明Person类型的引用p指向Person类型的对象 p.show(); - 调用名字为show()的成员方法 1. ...
随机推荐
- php闭包bindTo方法用法
从手册知道,Closure::bindTo — 复制当前闭包对象,绑定指定的$this对象和类作用域. 创建并返回一个 匿名函数, 它与当前对象的函数体相同.绑定了同样变量,但可以绑定不同的对象,也可 ...
- Linux内核分析 - 网络[十四]:IP选项
Linux内核分析 - 网络[十四]:IP选项 标签: linux内核网络structsocketdst 2012-04-25 17:14 5639人阅读 评论(1) 收藏 举报 分类: 内核协议栈 ...
- Halcon二维仿射变换实例探究
二维仿射变换,顾名思义就是在二维平面内,对对象进行平移.旋转.缩放等变换的行为(当然还有其他的变换,这里仅论述这三种最常见的). Halcon中进行仿射变换的常见步骤如下: ① 通过hom_mat2d ...
- Halcon阈值化算子dual_threshold和var_threshold的理解
Halcon中阈值二值化的算子众多,通常用得最多的有threshold.binary_threshold.dyn_threshold等. threshold是最简单的阈值分割算子,理解最为简单:bin ...
- py学习之FTP
1.FTP之参数解析与命令分发 a) 层级目录如下 b) 配置文件如下 #!/usr/bin/env python # -*- coding:utf8 -*- import socket sk=soc ...
- [Selenium] 针对下拉菜单出现之后又立马消失的问题,通过Javascript改变元素的可见属性
public void clickDateDropDownButton() { SeleniumUtil.jsClick(driver, page.getDateDropdownButtonOfInv ...
- [分享]PY的Boost自动编译程序 1.1 根据环境自动编译
Python写的Boost自动编译程序 1.1 改进: 根据自己的环境筛选出已安装环境,并列出 环境提供选择. 支持X64位的自动参数编译. 可以选择编译的参数,其他版本持续改进中 自动编译自动安装到 ...
- Windows 访问 Oracle
开发环境 vs2010 安装ODTwithODAC1120320_32bit.zip Win2003 64 位 1.不使用EF需要安装ODAC112021Xcopy_x64.zip开发环境中的Orac ...
- maven scope简单说明
compile:默认的scope.任何定义在compile scope下的依赖将会在所有的class paths下可用.maven工程会将其打包到最终的arifact中.如果你构建一个WAR类型的ar ...
- UVa 1025 A Spy in the Metro (DP动态规划)
题意:一个间谍要从第一个车站到第n个车站去会见另一个,在是期间有n个车站,有来回的车站,让你在时间T内时到达n,并且等车时间最短, 也就是尽量多坐车,最后输出最少等待时间. 析:这个挺复杂,首先时间是 ...