繁体   English   中英

Java,Spring,JSP, <form> 。 BeanResult&#39;command&#39;的BindingResult和普通目标对象都不能用作请求属性

[英]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中设置其属性 ,但是当我们显示空表单时,它必须已经可用。

我们将分两步解决问题:

  1. 将表单支持对象添加到显示表单的控制器方法中的模型中,以使其可用于表单-(例如)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"; } 
  2. 将表单支持对象的名称添加到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中发生:

  1. 将表单支持对象的名称添加到form:form标记中,如下所示:

<form:form modelAttribute="myFormBackingObjectName">

告诉表单,这意味着我们为实体/表单支持对象使用的名称。


您的index.jsp可能不是由控制器中的方法返回的。 至少,代码没有显示它。 但这还不够,该方法还必须提供一个名为“ command”的表单支持对象/实体,换句话说,就是将一个名为“ command”的对象保存在模型中。

由于您的form:form标记中包含commandName =“ command”(这是表示modelAttribute =“ command”的较旧方法),因此该表单试图在模型中查找“ command”对象作为请求属性。 但是控制器中的调用方法必须首先将该实体保存在模型中,以使其可用于表单。

如果清楚的话,那么进一步阅读就是对同一问题的答案。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM