你正在尝试使用Spring MVC的form标签。
此标记呈现HTML form标记,并向内部标记公开绑定路径以进行绑定。它将命令对象放入中,
PageContext以便内部标签可以访问该命令对象。
[..]
假设我们有一个名为的域对象User。这是一个
JavaBean,具有诸如firstName和的属性lastName。我们将其用作返回的表单控制器的 表单支持对象
form.jsp。
换句话说,
Spring MVC将提取命令对象并将其类型用作绑定内部标记(如或)的path表达式的蓝图,以呈现HTML 元素。
forminputcheckboxform
该命令对象也称为模型属性,其名称在form标签
modelAttribute或
commandName属性中指定。你已经在JSP中省略了它
<form:form>
你可以明确指定一个名称。这两个都是等效的。
<form:form modelAttribute="some-example-name"><form:form commandName="some-example-name">
在默认属性名称是command(你在错误信息看)。模型属性是对象,通常是POJO或POJO的集合,你的应用程序将其提供给Spring MVC堆栈,并且Spring MVC堆栈将其公开给你的视图(即MVC中的M到V)。
Spring MVC收集所有模型属性
ModelMap(它们都有名称),对于JSP,将它们转移到
HttpServletRequest属性中,在此JSP标签和EL表达式可以访问它们。
在你的示例中,
@Controller用于处理GET路径的处理程序方法/movies添加了一个模型属性
model.addAttribute("movies", movies); // not named 'command'然后转发到index.jsp。然后,此JSP尝试渲染
<form:form> ... <form:input path="name" type="text" id="name" /> ...</form:form>
在呈现此代码时,FormTag(实际上是InputTag)会尝试查找名为command(默认属性名称)的模型属性,以便它可以生成一个
HTML <input>元素,该元素具有name从path表达式和相应的属性值(即)构造的属性。的结果
Movie#getFilmName()。
由于找不到它,它会引发你看到的异常
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'command' available as request attribute
JSP引擎将其捕获并以500状态代码响应。如果你想利用MoviePOJO简单地正确构造表单,可以使用以下命令显式添加模型属性
model.addAttribute("movie", new Movie());或让Spring MVC为你创建并添加一个(必须具有可访问的无参数构造函数)
@RequestMapping(path = "/movies", method = RequestMethod.GET)public String homePage(@ModelAttribute("command") Movie movie, Model model) {...}或者,
@ModelAttribute在你的
@Controller班级中添加带注释的方法
@ModelAttribute("command")public Movie defaultInstance() { Movie movie = new Movie(); movie.setFilmName("Rocky II"); return movie;}请注意,
Spring MVC将调用此方法,并针对由封装处理的每个请求,将返回的对象隐式添加到其模型属性中@Controller。
你可能从此描述中猜测到,
Spring的
form标签更适合
<form>从具有实际值的现有对象中呈现HTML 。如果你只想创建一个
blank <form>,那么自己构造而不依赖任何模型属性可能更合适。
<form method="post" action="${pageContext.request.contextPath}/movies"> <input name="filmName" type="text" /> <input type="submit" value="Upload" /></form>在接收方,你的POST处理程序方法仍将能够提取filmName输入值并将其用于初始化Movie对象。
常见错误
正如我们所看到的,
FormTag查找名为一个模型属性
command默认或名称在任一指定
modelAttribute或
commandName。确保使用正确的名称。
ModelMap有一个addAttribute(Object)增加
Map使用生成的名称为其提供的属性。
一般惯例是
返回[属性的]的小写形式的短名称
Class,根据
JavaBeans属性的命名规则:那么,
com.myapp.Product变得
product;
com.myapp.MyProduct成为
myProduct; com.myapp.UKProduct变成
UKProduct
如果你使用的是这种(或类似的)方法,或者使用的是代表模型属性的@RequestMapping 受支持的返回类型之一,请确保生成的名称符合你的期望。
另一个常见的错误是
@Controller完全绕过你的方法。典型的Spring MVC应用程序遵循以下模式:
- 发送HTTP GET请求
DispatcherServlet
选择@RequestMapping
处理请求的方法- 处理程序方法生成一些模型属性并返回视图名称
DispatcherServlet
向HttpServletRequest
与视图名称相对应的JSP 添加模型属性并将其转发到JSP- JSP呈现响应
如果由于某种错误配置而
@RequestMapping完全跳过了该方法,则将不会添加属性。这可能发生
- 如果你的HTTP请求URI直接访问你的JSP资源,例如 因为它们是可访问的,即。外面
WEB-INF
,或 - 如果
welcome-list
你的中web.xm
l包含你的JSP资源,则Servlet容器将直接呈现它,从而完全绕过Spring MVC
堆栈
你希望@Controller
以一种或另一种方式调用你的模型,以便适当地添加模型属性。
这BindingResult有什么关系?
A BindingResult是用于初始化或验证模型属性的容器。在Spring MVC的文档状态
该
Errors或
BindingResult参数必须遵循被立即绑定方法签名可能有不止一个模型对象和Spring将创建一个单独的模型对象
BindingResult为他们每个人的情况下[…]
换句话说,如果要使用
BindingResult,则必须在
@RequestMapping方法中遵循相应的
model属性参数
@RequestMapping(path = "/movies", method = RequestMethod.POST)public String upload(@ModelAttribute("movie") Movie movie, BindingResult errors) {BindingResult对象也被视为模型属性。
Spring MVC使用简单的命名约定来管理它们,从而使查找对应的常规模型属性变得容易。由于
BindingResult包含有关模型属性的更多数据(例如,验证错误),
FormTag因此首先尝试绑定到该属性。但是,由于它们并存,因此没有一个就不可能存在。



