ModelAndView.addObject与Model.addAttribute

Voj*_*ech 4 spring-mvc

美好的一天,我正在学习Spring MVC,我正在按照本教程编写我的小型webapp,但我稍微将其修改为"任务列表"而不是"用户列表".有一件事我不清楚,所以我想请一个解释.这是我的edit.jsp:

<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>  
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>  
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring"%>
<html>
<head>
    <title>Edit task</title>
</head>
<body>
    <h1>Edit task</h1>
    <form:form method="post" action="/update" modelAttribute="task">
        <table>
            <tr>
                <td>Title</td>
                <td><form:input path="title"/></td>
            </tr>
            <tr>
                <td>Description</td>
                <td><form:textarea path="description"/></td>
            </tr>
            <tr>
                <td></td>
                <td><input type="submit" value="Save"/></td>
            </tr>
        </table>
    </form:form>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)

这是我的HomePageController.java(版本1)中的方法editTask:

 @RequestMapping("/edit")  
 public ModelAndView editTask(@RequestParam String id, @ModelAttribute Task task) {  
   // Retrieve task from the database
     task = taskService.getTask(id);
     ModelAndView model = new ModelAndView("edit");
     model.addObject("task", task);
     return model;
 }
Run Code Online (Sandbox Code Playgroud)

如果我单击编辑链接以编辑项目(例如/ TaskBook/edit?id = 1),则会显示一个表单,但不会填充该表单.所以我用这种方式改变了方法(版本2):

 @RequestMapping("/edit")  
 public String editTask(@RequestParam String id, Model model) {
     Task task = taskService.getTask(id);
     model.addAttribute("task", task);
     return "edit";
 }
Run Code Online (Sandbox Code Playgroud)

现在,在编辑任务时填充表单.我不明白版本1中的model.addObject("任务",任务)和版本2中的model.addAttribute("任务",任务)之间有什么区别.任务对象是存储在其他地方还是丢失了?请解释.我使用Spring Framework 3.2.1.

先感谢您.Vojtech.

编辑:如果我将editTask()更改为下面的代码,它的工作原理 - 填充表单.但是,如果某些任务数据被提交,我现在如何阅读呢?

@RequestMapping("/edit")  
public ModelAndView editTask(@RequestParam String id) {  
  task = taskService.getTask(id);
  ModelAndView model = new ModelAndView("edit");
  model.addObject("task", task);
  return model;
}
Run Code Online (Sandbox Code Playgroud)

Sot*_*lis 13

你遇到了一个不经常发生的边缘情况.我们一起来试试吧

@RequestMapping("/edit")  
public String editTask(@RequestParam String id, Model model) {
    Task task = taskService.getTask(id);
    model.addAttribute("task", task);
    return "edit";
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,Spring将从其中创建一个Model对象ModelAndViewContainer,并将其作为参数传递给您的方法.因此,如果您之前添加了模型属性,则可以在此处使用它们,并且您添加的模型属性将在稍后提供.您返回一个String视图名称.Spring将使用带有a的String ViewResolver来解析jsp要呈现或转发的视图或其他类型的视图.

有了这个

@RequestMapping("/edit")  
public ModelAndView editTask(@RequestParam String id, @ModelAttribute Task task) {  
    // Retrieve task from the database
    task = taskService.getTask(id);
    ModelAndView model = new ModelAndView("edit");
    model.addObject("task", task);
    return model;
}
Run Code Online (Sandbox Code Playgroud)

Spring,因为它@ModelAttribute会创建一个Task对象,并在调用(反射)方法时将其作为参数传递.在ModelAndView您创建对象,添加和回报将与被合并ModelAndView对象中包含的ModelAndViewContainer由Spring为您的要求进行管理.因此,您在此处添加的内容也将在稍后提供.

故障:它似乎ModelAttribute优先于模型属性,因此不会被添加到ModelAndView对象的模型属性覆盖.实际上会被写入你的ModelAndView对象,覆盖你的"task"属性.请记住,如果没有value@ModelAttribute注释指定属性,它会使用参数的类型为其指定名称.例如,Task==> "task",List<Task==> taskList等.