【问题标题】:ModelAndView.addObject vs Model.addAttributeModelAndView.addObject 与 Model.addAttribute
【发布时间】:2013-10-04 14:26:35
【问题描述】:

美好的一天,我正在学习 Spring MVC,我正在按照 this tutorial 编写我的小型 Web 应用程序,但我将其稍微修改为“任务列表”而不是“用户列表”。有一件事我不清楚,所以我想要求解释。这是我的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("task", task) 和版本 2 中的 model.addAttribute("task", task) 有什么区别。任务对象是存储在其他地方还是丢失了?请解释。我使用 Spring Framework 3.2.1。

提前谢谢你。沃杰科技。

编辑: 如果我将 editTask() 更改为下面的代码,它可以工作 - 表单已填充。但是如果提交了一些任务数据,我现在怎么读呢?

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

【问题讨论】:

  • 帮我一个忙,测试你的第一个editTask(),但删除@ModelAttribute 参数。而是在您的方法中创建 Task 引用。看看会发生什么。
  • 我更改了 editTask() - 请参阅上面的已编辑帖子 - 表单仍未填充。
  • 没有同样的效果。完全摆脱Task 参数。在方法中用作Task task = taskService.getTask(id);。此外,将代码放入 cmets 很难阅读。请考虑改为编辑您的答案。
  • 所以我删除了 Task 参数并开始工作。所以这可能意味着由 model.addObject("task", task) 设置的任务被作为参数传递的任务覆盖,对吗?如果现在有一些提交,我如何读取任务数据?

标签: spring-mvc


【解决方案1】:

您遇到了不经常发生的极端情况。我们去试试吧

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

在这种情况下,Spring 将从其ModelAndViewContainer 创建一个Model 对象并将其作为参数传递给您的方法。因此,如果您之前添加了模型属性,它们将在此处可供您使用,而您添加的属性稍后将可用。您返回一个 String 视图名称。 Spring 将使用该 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;
}

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

问题:看来ModelAttribute 优先于模型属性,因此它不会被您添加到ModelAndView 对象的模型属性覆盖。实际上 it 被写入您的 ModelAndView 对象,覆盖您的 "task" 属性。请记住,如果您没有为@ModelAttribute 注释指定value 属性,它会使用参数的类型为其命名。例如,Task ==> "task"List&lt;Task ==> taskList

【讨论】:

    猜你喜欢
    • 2021-03-10
    • 2015-07-06
    • 2018-03-24
    • 2020-09-25
    • 2020-05-11
    • 1970-01-01
    • 2014-06-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多