简体   繁体   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

Hey, everyone! 嘿大家!

I can't understand why it happens when I try to open webapp: 我无法理解为什么在尝试打开webapp时会发生这种情况:

Neither BindingResult nor plain target object for bean name 'command' available as request attribute

and

org.apache.jasper.JasperException: An exception occurred processing JSP page /index.jsp at line 53

Here is form from index.jsp 这是来自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>

Here is Controller 这是管制员

@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";
    }
}

The following is Stacktrace and Root Cause 以下是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)

Sorry, if something has been missed. 抱歉,如果错过了什么。 Thanks! 谢谢!

Why does this happen? 为什么会这样?

The complete answer is here . 完整的答案在这里 This is just my easier explanation for Spring beginners. 这只是我对Spring初学者的简单解释。

The short answer is, that the Spring form does not work without a "form backing object" or "command object", as it is also called in the Spring docs. 简短的答案是,没有“表单支持对象”或“命令对象”,Spring表单就无法工作,因为它在Spring文档中也被称为。

The index.jsp should be returned by a controller method, that makes a " bean name 'command' available to the form as request attribute " as stated in the exception. index.jsp应该由控制器方法返回,该方法使异常中所述的“ bean名称'命令'作为请求属性可供表单使用 ”。

--- Long answer --- -长答案-

The Spring form documentation reads: Spring表单文档显示为:

"...form:form tag renders an HTML 'form' tag and exposes a binding path to inner tags for binding. It puts the command object in the PageContext so that the command object can be accessed by inner tags ..." “ ... form:form标记呈现一个HTML'form'标记,并向内部标记公开一个绑定路径以进行绑定。 它将命令对象放置在PageContext中,以便内部标记可以访问命令对象 ...”

This means, that the inner tags (like form:input) need a 'command object' because they want to bind to it. 这意味着内部标签(如form:input)需要一个“命令对象”,因为它们想绑定到它。

So, what is this "command object" (also known as the form backing object) and where does it come from? 那么,这个“命令对象”是什么(又称为表单支持对象),它是从哪里来的呢?

Read this a couple of times: 读几次:

  • The form backing object is the bean/entity that the form is dealing with - like for example the form addItem.jsp is dealing with an entity "Item". 表单支持对象是表单正在处理的bean /实体-例如表单addItem.jsp正在处理实体“ Item”。 The entity/command object comes from the the method in the form controller which returns the form . 实体/命令对象来自表单控制器中的方法,该方法返回form

  • The form backing object/bean/entity is going to have its properties set in the form , but it needs to be available already when we show the empty form. 表单支持对象/ bean /实体将在form中设置其属性 ,但是当我们显示空表单时,它必须已经可用。

We will solve our problem in two steps: 我们将分两步解决问题:

  1. add the form backing object to the model in controller method that shows the form, to make it accessible for the form - (for example) addItem.jsp 将表单支持对象添加到显示表单的控制器方法中的模型中,以使其可用于表单-(例如)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. add the name of the form backing object to the form:form tag in the addItem.jsp like this: 将表单支持对象的名称添加到addItem.jsp中的form:form标记中,如下所示:

    <form:form modelAttribute="item">

To understand what is happening in the step 2., read the explanation below: 要了解步骤2中发生的情况,请阅读以下说明:

If we run the app after step 1, normally we should still get the same exception: IllegalStateException: Neither BindingResult nor plain target object for bean name 'command' available as request attribute 如果我们在步骤1之后运行应用程序,通常我们仍应获得相同的异常: IllegalStateException: Bean名称“ command”的 BindingResult或普通目标对象都不能用作请求属性

(It is possible, that after adding an entity named 'command' to the code in the question above, it starts to work, because the commandName="command" works the same way as the modelAttribute="command" - see explanation below.) (可能的是,将一个名为'command'的实体添加到上述问题中的代码之后,它开始起作用,因为commandName =“ command”与modelAttribute =“ command”的工作方式相同-请参见下面的说明。 )

What is this - bean named 'command' ? 这个叫“命令”的bean是什么? Read the docs or the excerpt: 阅读文档或摘录:

...docs.spring.io/spring/docs/current/spring-framework-reference/html/view.html#view-jsp-formtaglib-formtag ... docs.spring.io/spring/docs/current/spring-framework-reference/html/view.html#view-jsp-formtaglib-formtag

... ...

<form:form>
  ...
</form:form>

... The preceding JSP assumes that the variable name of the form backing object is 'command'. ...前面的JSP假定表单支持对象的变量名是'command'。 If you have put the form backing object into the model under another name (definitely a best practice), then you can bind the form to the named variable like so: 如果已将表单支持对象以另一个名称(肯定是最佳实践)放入模型中,则可以将表单绑定到命名变量,如下所示:

<form:form modelAttribute="user">

... ...

This means: 这意味着:

A: a form:form will try to find a form backing object named 'command' in the model, even if it is not explicitly writen in the form:form tag 答:form:form会尝试在模型中找到名为“ command”的表单支持对象,即使未在form:form标记中明确写入该对象也是如此

<form:form> really means <form:form modelAttribute="command"> <form:form>真正含义是<form:form modelAttribute="command">

In this case, the form will not work if the form backing object/entity named 'command' is not available in the model. 在这种情况下,如果模型中没有名为“ command”的表单支持对象/实体,则该表单将无法工作。

B: When sending the form backing object/bean/entity to the form (packaged in the model), we must either: B:将表单支持对象/ bean /实体发送到表单(包装在模型中)时,我们必须:

  • name it 'command' 将其命名为“命令”

    or - (definitely a best practice) - 或-(绝对是最佳做法)-

  • name it whatewer we want, like in the sample code above model.addAttribute("item", new Item()); 命名为我们想要的名称,例如在model.addAttribute("item", new Item());上面的示例代码中model.addAttribute("item", new Item()); but then we must explicitly write the name of the form backing object in the form:form tag like this: 但是我们必须在form:form标记中显式编写表单支持对象的名称,如下所示:

<form:form modelAttribute="item">

The reason for the "Neither BindingResult nor plain target object..." exception may be: “既不是BindingResult也不是普通目标对象...”异常的原因可能是:

  • we did not put our form backing object named 'command' into the model in the controller method that shows the form 我们没有在显示表单的controller方法中将名为“ command”的表单支持对象放入模型中

  • we did not name our form backing object 'command' when we put it into the model and we did not tell the form to look in the model for the form backing object named 'item', 'user', or whatever 'myFormBackingObjectName' we used, when we put the form backing object/bean/entity into the model. 我们在将表单支持对象放入模型中时并没有为其命名,也没有告诉表单在模型中查找名为“ item”,“ user”或任何“ myFormBackingObjectName”的表单支持对象当我们将表单支持对象/ bean /实体放入模型时使用。

That happens in the step 2: 这在步骤2中发生:

  1. add the name of our form backing object to the form:form tag like this: 将表单支持对象的名称添加到form:form标记中,如下所示:

<form:form modelAttribute="myFormBackingObjectName">

This means, tell the form, what name we used for our entity/form backing object. 告诉表单,这意味着我们为实体/表单支持对象使用的名称。


Your index.jsp is probably not being returned by a method in the controller. 您的index.jsp可能不是由控制器中的方法返回的。 At least, the code is not showing it. 至少,代码没有显示它。 But that alone would still not be enough, that method would also have to make available a form backing object/entity, named 'command', in other words, save an object named 'command' in the model. 但这还不够,该方法还必须提供一个名为“ command”的表单支持对象/实体,换句话说,就是将一个名为“ command”的对象保存在模型中。

Since you have commandName="command" in your form:form tag (that is the older way of saying modelAttribute="command") the form is trying to find the 'command' object in the model as a request attribute. 由于您的form:form标记中包含commandName =“ command”(这是表示modelAttribute =“ command”的较旧方法),因此该表单试图在模型中查找“ command”对象作为请求属性。 But the calling method in controller must first save this entity in the model, to make it available for the form. 但是控制器中的调用方法必须首先将该实体保存在模型中,以使其可用于表单。

If this is clear, further reading is this answer to the same question. 如果清楚的话,那么进一步阅读就是对同一问题的答案。

暂无
暂无

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

相关问题 Spring MVC产生“ Bean名称&#39;command&#39;的BindingResult和普通目标对象异常都不能用作请求属性” - Spring MVC produces “Neither BindingResult nor plain target object exception for bean name 'command' available as request attribute” 处理JSP页面时出现JasperException:BeanResult&#39;command&#39;的BindingResult和普通目标对象都不能用作请求属性 - JasperException when processing JSP page: Neither BindingResult nor plain target object for bean name 'command' available as request attribute Bean名称的BindingResult和普通目标对象都不能用作请求属性(Spring MVC) - Neither BindingResult nor plain target object for bean name available as request attribute (Spring MVC) Spring MVC:BindingResult和bean名称&#39;POJO&#39;的普通目标对象都不能作为请求属性使用 - Spring MVC : Neither BindingResult nor plain target object for bean name 'POJO' available as request attribute Spring-mvc 错误:Bean 名称“userBean”的 BindingResult 和普通目标对象都不能用作请求属性 - Spring-mvc error: Neither BindingResult nor plain target object for bean name 'userBean' available as request attribute BeanResult&#39;student&#39;的BindingResult或普通目标对象都不能用作请求属性-Spring MVC - Neither BindingResult nor plain target object for bean name 'student' available as request attribute - Spring MVC 春季| 休眠| Thymeleaf:BeanResult&#39;id&#39;的BindingResult或普通目标对象都不能用作请求属性 - Spring | Hibernate | Thymeleaf: Neither BindingResult nor plain target object for bean name 'id' available as request attribute Spring 3 MVC:Bean名称的BindingResult和普通目标对象都不可用作请求属性 - Spring 3 MVC:Neither BindingResult nor plain target object for bean name available as request attribute Spring Webflow IllegalStateException:BeanResult的BindingResult和普通目标对象都不可用作请求属性 - Spring Webflow IllegalStateException: Neither BindingResult nor plain target object for bean name available as request attribute 简单的Java Web验证Bean名称“数字”的BindingResult和普通目标对象都不能用作请求属性 - Simple Java Web validation Neither BindingResult nor plain target object for bean name 'number' available as request attribute
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM