ModelAndView.addObject与Model.addAttribute

时间:2013-10-04 14:26:36

标签: spring-mvc

美好的一天,我正在学习Spring MVC,我正在this tutorial之后编写我的小型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>

这是我的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;
 }

如果单击编辑链接以编辑项目(例如/ 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";
 }

现在编辑任务时填充表单。我不明白版本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;
}

1 个答案:

答案 0 :(得分:12)

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

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

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

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

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