[英]Spring MVC produces “Neither BindingResult nor plain target object exception for bean name 'command' available as request attribute”
[英]Java, Spring, JSP, <form>. Neither BindingResult nor plain target object for bean name 'command' available as request attribute
嘿大家!
我无法理解为什么在尝试打开webapp时会发生这种情况:
Neither BindingResult nor plain target object for bean name 'command' available as request attribute
和
org.apache.jasper.JasperException: An exception occurred processing JSP page /index.jsp at line 53
这是来自index.jsp的form
51 <c:url var="addAction" value="/email/add.form"/>
52 <form:form action="${addAction}" commandName="command">
53 <form:input path="email" type="email" placeholder="Enter email" class="cell"/>
54 <input type="submit" class="button" value="<spring:message text="Send"/>"/>
55 </form:form>
这是管制员
@Controller
public class EmailController {
private EmailService emailService;
@Autowired
@Qualifier("emailService")
public void setEmailService(EmailService emailService) {
this.emailService = emailService;
}
@RequestMapping(value = "/email/add", method = RequestMethod.POST)
public String addEmail(@ModelAttribute("email") EmailEntity emailEntity) {
this.emailService.addEmail(emailEntity);
return "redirect:/email.form";
}
}
以下是Stacktrace和根本原因
Stacktrace:
org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:584)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:476)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:385)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:329)
javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
Root Cause
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'command' available as request attribute
org.springframework.web.servlet.support.BindStatus.<init>(BindStatus.java:144)
org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.getBindStatus(AbstractDataBoundFormElementTag.java:168)
org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.getPropertyPath(AbstractDataBoundFormElementTag.java:188)
org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.getName(AbstractDataBoundFormElementTag.java:154)
org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.autogenerateId(AbstractDataBoundFormElementTag.java:141)
org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.resolveId(AbstractDataBoundFormElementTag.java:132)
org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.writeDefaultAttributes(AbstractDataBoundFormElementTag.java:116)
org.springframework.web.servlet.tags.form.AbstractHtmlElementTag.writeDefaultAttributes(AbstractHtmlElementTag.java:422)
org.springframework.web.servlet.tags.form.InputTag.writeTagContent(InputTag.java:142)
org.springframework.web.servlet.tags.form.AbstractFormTag.doStartTagInternal(AbstractFormTag.java:84)
org.springframework.web.servlet.tags.RequestContextAwareTag.doStartTag(RequestContextAwareTag.java:80)
org.apache.jsp.index_jsp._jspx_meth_form_005finput_005f0(index_jsp.java:323)
org.apache.jsp.index_jsp._jspx_meth_form_005fform_005f0(index_jsp.java:271)
org.apache.jsp.index_jsp._jspService(index_jsp.java:184)
org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:443)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:385)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:329)
javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
抱歉,如果错过了什么。 谢谢!
为什么会这样?
完整的答案在这里 。 这只是我对Spring初学者的简单解释。
简短的答案是,没有“表单支持对象”或“命令对象”,Spring表单就无法工作,因为它在Spring文档中也被称为。
index.jsp应该由控制器方法返回,该方法使异常中所述的“ bean名称'命令'作为请求属性可供表单使用 ”。
-长答案-
Spring表单文档显示为:
“ ... form:form标记呈现一个HTML'form'标记,并向内部标记公开一个绑定路径以进行绑定。 它将命令对象放置在PageContext中,以便内部标记可以访问该命令对象 ...”
这意味着内部标签(如form:input)需要一个“命令对象”,因为它们想绑定到它。
那么,这个“命令对象”是什么(又称为表单支持对象),它是从哪里来的呢?
读几次:
表单支持对象是表单正在处理的bean /实体-例如表单addItem.jsp正在处理实体“ Item”。 实体/命令对象来自表单控制器中的方法,该方法返回form 。
表单支持对象/ bean /实体将在form中设置其属性 ,但是当我们显示空表单时,它必须已经可用。
我们将分两步解决问题:
将表单支持对象添加到显示表单的控制器方法中的模型中,以使其可用于表单-(例如)addItem.jsp
@RequestMapping("/add-item") public String showAddItemForm(Model model) { // adding the form backing object/entity - here for example named item // to the model "as request attribute" (see the exception in the question) model.addAttribute("item", new Item()); return "item/addItem"; }
将表单支持对象的名称添加到addItem.jsp中的form:form标记中,如下所示:
<form:form modelAttribute="item">
要了解步骤2中发生的情况,请阅读以下说明:
如果我们在步骤1之后运行应用程序,通常我们仍应获得相同的异常: IllegalStateException: Bean名称“ command”的 BindingResult或普通目标对象都不能用作请求属性
(可能的是,将一个名为'command'的实体添加到上述问题中的代码之后,它开始起作用,因为commandName =“ command”与modelAttribute =“ command”的工作方式相同-请参见下面的说明。 )
这个叫“命令”的bean是什么? 阅读文档或摘录:
... docs.spring.io/spring/docs/current/spring-framework-reference/html/view.html#view-jsp-formtaglib-formtag
...
<form:form>
...
</form:form>
...前面的JSP假定表单支持对象的变量名是'command'。 如果已将表单支持对象以另一个名称(肯定是最佳实践)放入模型中,则可以将表单绑定到命名变量,如下所示:
<form:form modelAttribute="user">
...
这意味着:
答:form:form会尝试在模型中找到名为“ command”的表单支持对象,即使未在form:form标记中明确写入该对象也是如此
<form:form>
真正含义是<form:form modelAttribute="command">
在这种情况下,如果模型中没有名为“ command”的表单支持对象/实体,则该表单将无法工作。
B:将表单支持对象/ bean /实体发送到表单(包装在模型中)时,我们必须:
将其命名为“命令”
或-(绝对是最佳做法)-
命名为我们想要的名称,例如在model.addAttribute("item", new Item());
上面的示例代码中model.addAttribute("item", new Item());
但是我们必须在form:form标记中显式编写表单支持对象的名称,如下所示:
<form:form modelAttribute="item">
“既不是BindingResult也不是普通目标对象...”异常的原因可能是:
我们没有在显示表单的controller方法中将名为“ command”的表单支持对象放入模型中
我们在将表单支持对象放入模型中时并没有为其命名,也没有告诉表单在模型中查找名为“ item”,“ user”或任何“ myFormBackingObjectName”的表单支持对象当我们将表单支持对象/ bean /实体放入模型时使用。
这在步骤2中发生:
<form:form modelAttribute="myFormBackingObjectName">
告诉表单,这意味着我们为实体/表单支持对象使用的名称。
您的index.jsp可能不是由控制器中的方法返回的。 至少,代码没有显示它。 但这还不够,该方法还必须提供一个名为“ command”的表单支持对象/实体,换句话说,就是将一个名为“ command”的对象保存在模型中。
由于您的form:form标记中包含commandName =“ command”(这是表示modelAttribute =“ command”的较旧方法),因此该表单试图在模型中查找“ command”对象作为请求属性。 但是控制器中的调用方法必须首先将该实体保存在模型中,以使其可用于表单。
如果清楚的话,那么进一步阅读就是对同一问题的答案。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.