【问题标题】:SpringMVC - Java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean nameSpringMVC - Java.lang.IllegalStateException:Bean 名称的 BindingResult 和普通目标对象都不是
【发布时间】:2020-07-04 03:21:01
【问题描述】:

我是 Spring MVC 的新手,正在制作一个简单的 todo web 应用程序。绑定数据时出现以下错误。我相信带有 Springmvc 表单的 jsp 文件存在某些问题,它弄乱了绑定过程。我假设 bindingresult 会再次返回表单,但由于某种原因它不会。

org.apache.jasper.JasperException: java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'todo' available as request attribute
org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:549)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:465)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:390)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:334)
javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:168)
org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:303)
org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1257)
org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1037)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:980)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)

我的 updateToDo.jsp 表单

<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<html>
<head>
<title>update task</title>
<link href="webjars/bootstrap/4.5.0/css/bootstrap.min.css"
    rel="stylesheet">

</head>
<body>
    <div class="container">
        <H1>update your task!</H1>
    
        <form:form method="POST" commandName="todo">
            
            <fieldset class="form-group">
                <form:label path="description">Description:</form:label>
                <!-- required validates nulll -->
                <form:input path="description" type="text" class="form-control"
                    required="required" />
                <form:errors path="description" cssClass="text-warning" />
            </fieldset>

            <fieldset class="form-group">
                <form:label path="targetDate">Target Date</form:label>
                <form:input path="targetDate" type="Date" class="form-control"
                    required="required" />
                <form:errors path="targetDate" cssClass="text-warning" />

            </fieldset>
            <fieldset class="form-group">
                <form:radiobutton path="completion" value="true" />
                <form:radiobutton path="completion" value="false" />
                <form:errors path="targetDate" cssClass="text-warning" />
            </fieldset>

            <button type="submit" class="btn btn-success">Submit Update</button>
        </form:form>
        
    </div>
    <script src="webjars/jquery/3.5.1/jquery.min.js"></script>
    <script src="webjars/bootstrap/4.5.0/js/bootstrap.min.js"></script>

</body>
</html>

控制器

@Controller
public class ToDoController {

@Autowired
private ToDoService service;

@InitBinder
protected void initBinder(WebDataBinder binder) {
    SimpleDateFormat dateFormat = new SimpleDateFormat("mm/DD/yyyy");
    binder.registerCustomEditor(Date.class, new CustomDateEditor(
            dateFormat, false));
}

@RequestMapping(value = "/list-todo", method= RequestMethod.GET)
// HttpSession allows access to the session
public String showToDo(ModelMap model,  HttpSession httpSession) {
    String user = (String) httpSession.getAttribute("name");
    model.addAttribute("todos", service.retrieveTodos(user));
    return "list-todos";
}

// redirect to update form
@RequestMapping(value = "/update-todo", method= RequestMethod.GET)
public String getUpdateForm(ModelMap model, @RequestParam int id) {
    // To work with command bean
    model.addAttribute("todo", service.retrieveTodo(id));
    model.clear();
    return "updateToDo";
}

@RequestMapping(value = "/update-todo", method= RequestMethod.POST)
public String submitUpdate(ModelMap model, @Valid ToDo todo, BindingResult result) {
    if (result.hasErrors()) {
        return "redirect:/update-todo";
    }
    service.updateToDo(todo);
    model.clear();
    return "redirect:/list-todo";
}

// Will be executed first
@RequestMapping(value = "/add-todo", method= RequestMethod.GET)
public String showAddForm(ModelMap model) {
    model.addAttribute("todo", new ToDo());
    return "addToDo";
}


/*
 * Will be executed after form is submitted
 * @Valid ToDo - command bean from addToDo.jsp. 
 * @Valid to validate the information
 * @BindingResult showcases the result of the validation
 */
@RequestMapping(value = "/add-todo", method= RequestMethod.POST)
public String submitAddForm(ModelMap model , @Valid ToDo todo,  HttpSession httpSession, BindingResult result) {
    System.out.println("running" + result);
    // If there is validation error , return to addToDos page for user to fix the error
    if (result.hasErrors()) {
        return "redirect:/showAddForm";
    }
    String user = (String) httpSession.getAttribute("name");
    service.addTodo(user, todo.getDescription(), todo.getTargetDate(), false);      
    // Clears the url e.g. name?=jyj123
    model.clear();
    // return to the url which executes the showToDO
    return "redirect:/list-todo";
}

    // delete to do entry
 @RequestMapping(value = "/delete-todo", method= RequestMethod.GET) 
 public String deleteToDo(ModelMap model, @RequestParam int id) { 
     service.deleteTodo(id);
     model.clear();
     return "redirect:/list-todo"; }

}

【问题讨论】:

  • 也许我遗漏了一些东西,但我看不到从 .jsp 调用端点的位置。
  • @JWoodchuck getUpdateForm 方法在控制器中获取updateToDo.jsp

标签: java spring spring-mvc data-binding


【解决方案1】:

您正在调用model.clear(),因此删除了todo 属性。

    public String getUpdateForm(final ModelMap model, @RequestParam final int id) {
        // To work with command bean
        model.addAttribute("todo", service.retrieveTodo(id));
        model.clear();
        return "updateToDo";
    }

【讨论】:

    【解决方案2】:

    用外行的话来说,这就是 Spring MVC 的工作方式 -

    • 创建要绑定数据的 bean(通常在 GET 处理程序中)。 (这个 bean 被称为 命令对象

    • 将命令对象放入模型中

    • 返回视图名称。 (Spring会解析视图并将模型发送到视图)

    • 绑定数据(用户输入)到命令对象

    • 使用控制器中的数据检索命令对象POST 或其他类似的处理程序)


    您的问题的解决方案:

    您正在 GET 处理程序中调用 model.clear();。因此,在视图层中,模型是空的,并且没有 目标 bean(即命令对象)可用于绑定数据。

    所以删除mode.clear(); 调用。

    注意

    另一个常见的错误是在模型中的命令对象的键和commandName 的值&lt;form:form/&gt; 中使用不同的名称。

    即,如果您将命令对象放在模型中为model.put("fooBar", someFooBar);,则需要在视图中执行&lt;form:form commandName="fooBar" .../&gt;


    进一步阅读

    【讨论】:

    • 感谢您的回答。我的印象是 model.clear 只删除了 URL 中的变量
    猜你喜欢
    • 2016-02-17
    • 2014-09-25
    • 1970-01-01
    • 2020-09-26
    • 2018-01-07
    • 2020-12-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多