Java 对方法参数使用@modeldattribute
如本节所述 对方法参数使用@modeldattribute 方法参数上的@ModelAttribute指示该参数应 可以从模型中检索 但我观察到,即使没有使用@modeldattribute注释UserDetail,UserDetail也能正确填充。下面是相关的代码片段Java 对方法参数使用@modeldattribute,java,spring-mvc,Java,Spring Mvc,如本节所述 对方法参数使用@modeldattribute 方法参数上的@ModelAttribute指示该参数应 可以从模型中检索 但我观察到,即使没有使用@modeldattribute注释UserDetail,UserDetail也能正确填充。下面是相关的代码片段 <form:form id="userForm" action="path/userDetail" method="post" commandName="userDetail"> @RequestMappi
<form:form id="userForm" action="path/userDetail" method="post" commandName="userDetail">
@RequestMapping(value="/userDetail", method=RequestMethod.POST)
public String processUserDetail(UserDetail userDetail, HttpServletRequest request, HttpServletResponse response, Locale locale)
{}
@RequestMapping(value=“/userDetail”,method=RequestMethod.POST)
公共字符串processUserDetail(UserDetail UserDetail、HttpServletRequest请求、HttpServletResponse响应、区域设置)
{}
所以我的问题是spring本身是否填充了处理程序方法参数中的项目自定义对象(在本例中为userDetail)
即使没有注释@modeldattribute。我相信@modeldattribute在呈现视图时起作用,但在提交spring时起作用
如果方法参数存在于模型中,则自动填充该参数?即使不注释@modeldattribute,handler方法也会解析参数吗? 是的,但是@modeldattribute更改的是发生适当解析的时间点。框架在参数解析过程中所做的是,它获取每个参数,并遍历已注册的解析程序列表,一旦找到支持该参数的第一个解析程序,它将解析该参数并移动到下一个参数 处理模型属性的解析器是。它被注册了两次,第一次只扫描用@modeldattribute注释的参数,第二次作为列表中的最后一次,即使没有注释,也会解析参数 您可以通过检查冲突解决程序的源来检查冲突解决程序的列表和顺序。注意,的两个注册,true/false参数确定注释是否是必需的
private List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() {
List<HandlerMethodArgumentResolver> resolvers = new ArrayList<HandlerMethodArgumentResolver>();
// Annotation-based argument resolution
resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));
resolvers.add(new RequestParamMapMethodArgumentResolver());
resolvers.add(new PathVariableMethodArgumentResolver());
resolvers.add(new PathVariableMapMethodArgumentResolver());
resolvers.add(new MatrixVariableMethodArgumentResolver());
resolvers.add(new MatrixVariableMapMethodArgumentResolver());
resolvers.add(new ServletModelAttributeMethodProcessor(false));
resolvers.add(new RequestResponseBodyMethodProcessor(getMessageConverters()));
resolvers.add(new RequestPartMethodArgumentResolver(getMessageConverters()));
resolvers.add(new RequestHeaderMethodArgumentResolver(getBeanFactory()));
resolvers.add(new RequestHeaderMapMethodArgumentResolver());
resolvers.add(new ServletCookieValueMethodArgumentResolver(getBeanFactory()));
resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));
// Type-based argument resolution
resolvers.add(new ServletRequestMethodArgumentResolver());
resolvers.add(new ServletResponseMethodArgumentResolver());
resolvers.add(new HttpEntityMethodProcessor(getMessageConverters()));
resolvers.add(new RedirectAttributesMethodArgumentResolver());
resolvers.add(new ModelMethodProcessor());
resolvers.add(new MapMethodProcessor());
resolvers.add(new ErrorsMethodArgumentResolver());
resolvers.add(new SessionStatusMethodArgumentResolver());
resolvers.add(new UriComponentsBuilderMethodArgumentResolver());
// Custom arguments
if (getCustomArgumentResolvers() != null) {
resolvers.addAll(getCustomArgumentResolvers());
}
// Catch-all
resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true));
resolvers.add(new ServletModelAttributeMethodProcessor(true));
return resolvers;
}
private List getDefaultArgumentResolver(){
列表解析程序=新的ArrayList();
//基于注释的参数解析
add(新的RequestParamMethodArgumentResolver(getBeanFactory(),false));
add(新RequestParamMapMethodArgumentResolver());
添加(新的PathVariableMethodArgumentResolver());
添加(新的PathVariableMapMethodArgumentResolver());
添加(新矩阵variableMethodArgumentResolver());
add(新矩阵variableMapMethodArgumentResolver());
add(新的ServletModelAttributeMethodProcessor(false));
add(新的RequestResponseBodyMethodProcessor(getMessageConverters());
添加(新的RequestPartMethodArgumentResolver(getMessageConverters());
add(新的RequestHeaderMethodArgumentResolver(getBeanFactory());
add(newrequestHeaderMapMethodArgumentResolver());
add(新的ServletCookieValueMethodArgumentResolver(getBeanFactory());
add(新表达式ValueMethodArgumentResolver(getBeanFactory());
//基于类型的参数解析
add(新的ServletRequestMethodArgumentResolver());
添加(新的ServletResponseMethodArgumentResolver());
add(新的HttpEntityMethodProcessor(getMessageConverters());
添加(新的重定向属性MethodArgumentResolver());
add(新的ModelMethodProcessor());
add(新的MapMethodProcessor());
添加(新的ErrorsMethodArgumentResolver());
add(新SessionStatusMethodArgumentResolver());
添加(新的UriComponentsBuilderMethodArgumentResolver());
//自定义参数
if(getCustomArgumentResolver()!=null){
addAll(getCustomArgumentResolver());
}
//一网打尽
add(新的RequestParamMethodArgumentResolver(getBeanFactory(),true));
add(新的ServletModelAttributeMethodProcessor(true));
返回解析器;
}
TLDR
当您只关心填充您自己类型的实例时,这并不重要
长版本
在大多数情况下,添加或省略@modeldattribute
并没有什么区别。正如@MasterSlave已经提到的,同样的机制在幕后使用。在讨论何时使用@modeldattribute
很重要之前,让我解释一下模型的实际含义
从正在呈现的视图的角度来看,视图可以访问的是数据。在您的情况下,userDetail
。控制器负责向模型添加所有必要的数据。有很多方法可以实现这一点@modeldattribute
就是其中之一
显式使用@modeldattribute
的一个用例是定义可以访问数据的键@modeldattribute(“user”)UserDetail user
让视图通过键user
访问数据。否则它将是userDetail
在调用控制器方法之前,数据可能已经存在。它可能存储在会话中,或者由其他方法生成。这就是我的意思
应从模型中检索参数
但它可能存在于特定的键下,如“user”。同样,您必须通过@modeldattribute(“用户”)
提供名称。现有数据也可以是“简单”类型,如字符串
或日期
。在这种情况下,从模型中检索数据需要@modeldattribute
对于将由其他解析程序处理的类型的参数也是如此,例如
Map
或Locale
,因此风险。。。是不是它可以被其他的解析器匹配?可能是哪一个?我找不到这个例子,所以我已经从响应中删除了它