我在理解Spring 3 MVC中的表单提交方式时遇到了问题 .
我想要做的是创建一个控制器,它将获取用户的名字并显示给他 . 不知怎的,我已经做到了,但我真的不明白它是如何工作的 . 所以..
我有一个看起来像这样的表格:
<form:form method="post" modelAttribute="person">
<form:label path="firstName">First name</form:label>
<form:input path="firstName" />
<form:label path="lastName">Last name</form:label>
<form:input path="lastName" />
<input type="submit" value="Submit" />
</form:form>
我也有一个看起来像这样的控制器:
@Controller
public class HomeController {
@RequestMapping(value = "/", method = RequestMethod.GET)
public String showHelloPage(Model model) {
model.addAttribute("person", new Person());
return "home";
}
@RequestMapping(value = "/", method = RequestMethod.POST)
public String sayHello(Person person, Model model) {
model.addAttribute("person", person);
return "home";
}
}
要向用户显示欢迎消息,请在JSP页面中使用以下代码:
<c:if test="${not empty person.firstName and not empty person.lastName}">
Hello ${person.firstName} ${person.lastName}!
</c:if>
它有效(我省略了XML配置文件,因为它们与问题无关) .
我认为表单中的“modelAttribute”属性指向bean变量,该变量应填充输入值(在“路径”属性中设置) . 但看起来,它的工作方式却截然不同 . 如果我删除该行
model.addAttribute("person", new Person());
从“showHelloPage”方法我得到一个(常见的)异常“既不是BindingResult也不是......” .
另外,在开始时,“sayHello”方法看起来像:
(...)
public String sayHello(@ModelAttribute("person") Person person, Model model) {
(...)
我的意思是,它有“ModelAttribute”注释 . 我添加了它,因为在我读过的教程中,它始终存在 . 但是在我删除之后,一切都运行良好,就像之前一样 .
So my question is - "ModelAttribute" anonnatation的用途是什么?是否可以在表单中省略"modelAttribute"属性?第二部分,使表单自动绑定输入' values to the proper bean'属性(将被声明为方法参数)的方式(可能是一些注释)是什么?在发送表单之前无需添加空bean(因为我现在必须这样做) .
感谢您的回复(不是Spring文档的链接,因为我已经阅读过了) .
1 回答
在这种情况下,@ModelAttribute注释用于标识Spring应添加为模型属性的对象 . 模型属性是
HttpServletRequest
属性的抽象 . 基本上,它们是由某些键标识的对象,它们将进入HttpServletRequest
属性 . 您可以通过手动添加Model#addAttribute(String, Object)
属性,使用@ModelAttribute
注释方法或使用@ModelAttribute
注释方法参数来执行此操作 .你需要了解的是Spring如何解析你的处理程序方法参数并注入参数 . 它使用HandlerMethodArgumentResolver接口来执行此操作 . 有许多实现类(参见javadoc),每个类都有责任
resolveArgument()
通过反射返回Spring将用于invoke()
处理程序方法的参数 . 如果HandlerMethodArgumentResolver
supportsParameter()
方法为特定参数返回true
,则Spring将仅调用resolveArgument()
方法 .这里讨论的
HandlerMethodArgumentResolver
实现是ServletModelAttributeMethodProcessor,它从ModelAttributeMethodProcessor延伸出来Spring 天(3.2)将register这个
HandlerMethodArgumentResolver
和其他人当Spring需要调用你的处理程序方法时,它将遍历参数类型并通过上面的列表并使用第一个
supportsParameter()
.请注意,添加了两个
ServletModelAttributeMethodProcessor
实例(一个在//catch all
注释之后) .ModelAttributeMethodProcessor
有一个annotationNotRequired
字段,告诉它是否应该查找@ModelAttribute
. 第一个实例必须查找@ModelAttribute
,第二个实例不查找 . Spring会这样做,以便您可以注册自己的HandlerMethodArgumentResolver
实例,请参阅// Custom arguments
注释 .特别
在这种情况下,您的
Person
参数是否已注释无关紧要 .ModelAttributeMethodProcessor
将解析它并绑定表单字段,即 . 请求参数,到实例的字段 . 你甚至不需要将它添加到model
,因为ModelAttributeMethodProcessor
类将处理它 .在你的
showHelloPage()
方法中需要使用
<form>
taglib . 这就是它解析input
字段的方式 .自动将指定参数(或方法返回值)添加到模型 .
不,
form
绑定在Model
中查找对象,并将其字段绑定到htmlinput
元素 .Spring
<form>
标记锁定到模型属性对象上,并使用其字段创建input
和label
元素 . 它没有找到你指定的名称(键)的模型属性,它会抛出异常,如你所见 .提供空bean的替代方法是自己创建html . 所有Spring的
<form>
都使用bean的字段名来创建input
元素 . 所以这创造类似的东西
Spring使用
name
属性将请求参数绑定到实例字段 .