modelattribute 参数可以绑定哪些类型的属性

JAVA(71)
在方法上使用&@ModelAttribute&注解
@ModelAttribute注解不仅可以用在方法上也可以用在方法参数上。本节讲述@ModelAttribute在方法上的使用,下一节将讲述其在方法参数上的使用。
在方法上使用&@ModelAttribute
注解的目的是添加一个或者多个model属性中。这些方法支持@RequestMapping方法对应的参数,但是不能直接和请求映射。&在同一个Controller中@ModelAttribute&注解的方法将先于@RequestMapping注解的方法被调用。请看下面的例子:
// 添加一个属性
// 方法的返回值以”account”作为键添加到了model中
// 你可以通过 @ModelAttribute(&myAccount&)来指定名称
@ModelAttribute
public Account addAccount(@RequestParam String number) {
return accountManager.findAccount(number);
// 添加多个属性
@ModelAttribute
public void populateModel(@RequestParam String number, Model model) {
model.addAttribute(accountManager.findAccount(number));
// add more ...
@ModelAttribute 方法用来将一般属性填充到model
中,如用状态或者宠物类型填充下拉列表,或者用来恢复一个如Account命令对象用来表示html表单中的数据。后一种情况在下一节中将作详细阐述。
请注意两种@ModelAttribute方法风格,第一种:通过返回对象添加属性。第二种:方法含有Model作为参数,通过Model来添加任何数量的属性。你可以根据需要去选择。
一个controller(控制器)可以含有任意数量的 @ModelAttribute方法。同一个controller中所有这些方法在将先于 @RequestMapping
方法调用。
@ModelAttribute&也可以定义在被@ControllerAdvice注解的类中,这些方法将被应用到很多controller中。想了解更多相关信息请看:&&&&
“这一节。
& 如果一个model attribute(模型属性)名没有被明确指定会怎样?
在这种情况下,将高根据模型属性的类型来分配默认的名称。例如,如果方法返回一个Account类型的对象,默认模型属性名是&account&.
你可以通过修改&@ModelAttribute&注解的value来修改模型属性的名称。如果想把属性直接添加到Model中.你可以使用适当的addAttribute(..)&重载方法。也就是说,带不带属性名都可以。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:146589次
积分:2612
积分:2612
排名:第10664名
原创:172篇
转载:44篇
译文:40篇
评论:15条
(1)(3)(2)(6)(3)(2)(34)(12)(11)(4)(3)(3)(2)(3)(3)(3)(107)(7)(4)(7)(13)(1)(2)(20)(2)<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
您的访问请求被拒绝 403 Forbidden - ITeye技术社区
您的访问请求被拒绝
亲爱的会员,您的IP地址所在网段被ITeye拒绝服务,这可能是以下两种情况导致:
一、您所在的网段内有网络爬虫大量抓取ITeye网页,为保证其他人流畅的访问ITeye,该网段被ITeye拒绝
二、您通过某个代理服务器访问ITeye网站,该代理服务器被网络爬虫利用,大量抓取ITeye网页
请您点击按钮解除封锁&一、@ModelAttribute 注解
对方法标注 @ModelAttribute 注解,在调用各个目标方法前都会去调用 @ModelAttribute 标记的注解。本质上来说,允许我们在调用目标方法前操纵模型数据。
1.在 @ModelAttribute 标注的方法处向模型中存入数据
说明一下:在@ModelAttribute 标注的方法处,可以入参的类型和目标方法处允许的入参类型一致,如 @RequestParam 标注的请求参数等等。
有两种方式:
目标方法:
@RequestMapping("/updateStudent")
public String update(Student student) {
System.out.println("student: " + student);
return "success";
(1)通过向入参处添加 Model 类型或 Map 类型的参数(不推荐)
@ModelAttribute
public void getStudent(@RequestParam(value = "id", required = false) String idStr, Map&String, Object& map) {
Integer id = Integer.parseInt(idStr);
System.out.println("student id: " + id);
map.put("student", new Student(1, "lisi", 23));
} catch(NumberFormatException ignored) {
在调用目标方法前,"student" 会被放入到 Model 中。至于说为什么不推荐此种用法,是因为,最终还会向 model 中添加一个 key 为 void,值为 null 的数据。如图:
(2)通过 @ModelAttribute 注解的 value 属性和 @ModelAttribute 标注的方法返回值(推荐)
@ModelAttribute("student")
public Student getStudent(@RequestParam(value = "id", required = false) String idStr, Map&String, Object& map) {
Student student = null;
Integer id = Integer.parseInt(idStr);
System.out.println("student id: " + id);
student = new Student(1, "lisi", 23);
} catch(NumberFormatException ignored) {
在调用目标方法前,model 中的数据:
model 中只有一个键值对。这种写法更加优雅。
总结:SpringMVC 在调用目标方法前,将 @ModelAttribute 注解的 value 属性值作为 key , 返回值作为 value,存入到 model 中。
源码分析:
org.springframework.web.bind.annotation.support.HandlerMethodInvoker#invokeHandlerMethod
1 public final Object invokeHandlerMethod(Method handlerMethod, Object handler,
NativeWebRequest webRequest, ExtendedModelMap implicitModel) throws Exception {
Method handlerMethodToInvoke = BridgeMethodResolver.findBridgedMethod(handlerMethod);
boolean debug = logger.isDebugEnabled();
for (String attrName : this.methodResolver.getActualSessionAttributeNames()) {
Object attrValue = this.sessionAttributeStore.retrieveAttribute(webRequest, attrName);
if (attrValue != null) {
implicitModel.addAttribute(attrName, attrValue);
//开始调用标注有 @ModelAttribute 注解的方法
for (Method attributeMethod : this.methodResolver.getModelAttributeMethods()) {
Method attributeMethodToInvoke = BridgeMethodResolver.findBridgedMethod(attributeMethod);
Object[] args = resolveHandlerArguments(attributeMethodToInvoke, handler, webRequest, implicitModel);
if (debug) {
logger.debug("Invoking model attribute method: " + attributeMethodToInvoke);
String attrName = AnnotationUtils.findAnnotation(attributeMethod, ModelAttribute.class).value();
if (!"".equals(attrName) && implicitModel.containsAttribute(attrName)) {
ReflectionUtils.makeAccessible(attributeMethodToInvoke);
Object attrValue = attributeMethodToInvoke.invoke(handler, args);
if ("".equals(attrName)) {
Class&?& resolvedType = GenericTypeResolver.resolveReturnType(attributeMethodToInvoke, handler.getClass());
attrName = Conventions.getVariableNameForReturnType(attributeMethodToInvoke, resolvedType, attrValue);
if (!implicitModel.containsAttribute(attrName)) {
implicitModel.addAttribute(attrName, attrValue);
Object[] args = resolveHandlerArguments(handlerMethodToInvoke, handler, webRequest, implicitModel);
if (debug) {
logger.debug("Invoking request handler method: " + handlerMethodToInvoke);
ReflectionUtils.makeAccessible(handlerMethodToInvoke);
//调用目标方法
return handlerMethodToInvoke.invoke(handler, args);
catch (IllegalStateException ex) {
// Internal assertion failed (e.g. invalid signature):
// throw exception with full handler method context...
throw new HandlerMethodInvocationException(handlerMethodToInvoke, ex);
catch (InvocationTargetException ex) {
// User-defined @ModelAttribute/@InitBinder/@RequestMapping method threw an exception...
ReflectionUtils.rethrowException(ex.getTargetException());
return null;
行号14 处的 for 循环就是处理 @ModleAttribute 标注的方法的,在40行处调用目标方法&&在调用目标方法前调用 @ModelAttribute 标注的方法。
在 16 行处已经对请求参数做了一次解析&&在@ModelAttribute 标注的方法处,可以入参的类型和目标方法处允许的入参类型一致
&20行、25行、31行&&第二种方式,同时也明白如果 model 中包含相同的 key 时,是不会替换的。
2.在目标方法处读取模型中的数据
@ModelAttribute("student")
public Student getStudent() {
return new Student(1, "lisi", 23);
@ModelAttribute("student2")
public Student getStudent2() {
return new Student(2, "wangwu", 33);
(1)在目标方法入参处不使用 @ModelAttribute 注解
@RequestMapping("/updateStudent")
public String update(Student student2) {
System.out.println("student: " + student2);
return "success";
控制台输出:
student: Student{id=23, studentName='lisi', age=23}
(2)在目标方法入参处使用 @ModelAttribute 注解
@RequestMapping("/updateStudent")
public String update(@ModelAttribute("student2") Student student2) {
System.out.println("student: " + student2);
return "success";
控制台输出:
student: Student{id=23, studentName='wangwu', age=33}
(3)源码分析
org.springframework.web.bind.annotation.support.HandlerMethodInvoker#resolveHandlerArguments
这个方法行数太多了,我们只看关注点:
289行:如果目标方法入参有标记 @ModelAttribute ,获取它 的 value 属性。
else if (ModelAttribute.class.isInstance(paramAnn)) {
ModelAttribute attr = (ModelAttribute) paramA
attrName = attr.value();
annotationsFound++;
else if (attrName != null) {
WebDataBinder binder =
resolveModelAttribute(attrName, methodParam, implicitModel, webRequest, handler);
boolean assignBindingResult = (args.length & i + 1 && Errors.class.isAssignableFrom(paramTypes[i + 1]));
if (binder.getTarget() != null) {
doBind(binder, webRequest, validate, validationHints, !assignBindingResult);
args[i] = binder.getTarget();
if (assignBindingResult) {
args[i + 1] = binder.getBindingResult();
implicitModel.putAll(binder.getBindingResult().getModel());
不论是对目标方法入参有没有标注 @ModelAttribute 注解,最终都会执行到这里。
看标红的地方:在这里进行解析的。
private WebDataBinder resolveModelAttribute(String attrName, MethodParameter methodParam,
ExtendedModelMap implicitModel, NativeWebRequest webRequest, Object handler) throws Exception {
// Bind request parameter onto object...
String name = attrN
if ("".equals(name)) {
name = Conventions.getVariableNameForParameter(methodParam);
Class&?& paramType = methodParam.getParameterType();
Object bindO
if (implicitModel.containsKey(name)) {
bindObject = implicitModel.get(name);
else if (this.methodResolver.isSessionAttribute(name, paramType)) {
bindObject = this.sessionAttributeStore.retrieveAttribute(webRequest, name);
if (bindObject == null) {
raiseSessionRequiredException("Session attribute '" + name + "' required - not found in session");
bindObject = BeanUtils.instantiateClass(paramType);
WebDataBinder binder = createBinder(webRequest, bindObject, name);
initBinder(handler, name, binder, webRequest);
String name = attrN
if ("".equals(name)) {
  name = Conventions.getVariableNameForParameter(methodParam);
如果没有指定,则通过&&Conventions.getVariableNameForParameter(methodParam) 获取一个默认值。
if (implicitModel.containsKey(name)) {
  bindObject = implicitModel.get(name);
从 model中获取,最后执行绑定。
(4)总结:使用在目标方法入参处的 @ModelAttribute 只能起到一个 指定 attrName 的作用,即从 Model 获取数据的 key。
&1&目标方法处的实体形参命名与 @ModelAttribute 方法标注的方法返回值之间没有任何关系,只是类型有关系。
&2&在目标方法入参处不使用 @ModelAttribute 注解的情况:
不需要通过 @ModelAttribute 注解来指定需要使用哪个 @ModelAttribute 标注的方法的 value 属性值。存在多个的话,使用默认值。
&3&在目标方法入参处需要使用 @ModelAttribute 注解的情况:
存在多个 @ModelAttribute 标注的方法,返回值为同一个类型A,且 @ModelAttribute 的 value 属性值不同,在目标方法处,需要以 A 实体作为入参,但是需要不使用默认的 a ,而是需要使用指定
的 a2。这个时候,就需要在目标方法的入参处使用 @ModelAttribute,通过 value 属性来指定使用哪个。
二、@SessionAttribute
1.官方说明
2.对 SessionAttribute 这里有篇帖子总结的非常好,我这里就不再赘述。
3.我自己的理解:
@SessionAttribute 指的是 springmvc 的 session。向其中添加值得时候,同时会向 http session 中添加一条。在&sessionStatus.setComplete(); 的时候,会清空 sprinmvc
的 session,同时清除对应键的 http session 内容,但是通过,request.getSession.setAttribute() 方式添加的内容不会被清除掉。
其他情况下,springmvc session 和 http session使用情况相同。
阅读(...) 评论()}

我要回帖

更多关于 modelattribute注解 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信