ModelAndView.addObject vs Model.метод addattribute
Добрый день, я изучаю Spring MVC и пишу свое крошечное веб-приложение послеэтого урока , но я немного изменил его как "список задач", а не "список пользователей". Одна вещь мне не ясна, поэтому я хотел бы попросить объяснений. Это моя правка.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>
И это метод editTask в моем HomePageController.java (Версия 1):
@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";
}
Теперь форма заполняется, когда я редактирую задачу. Я не понимаю, в чем разница между моделями.addObject ("задача", task) в версии 1 и модели.addAttribute ("task", задача) в версии 2. Объект задачи хранится где-то еще или он потерян? Пожалуйста объяснить. Я использую 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;
}
1 ответ:
Вы попали в крайний случай, который встречается не очень часто. Давайте попробуем
@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
, чтобы решить, какой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
, который вы создаете, добавляете и возвращаете, будет объединен с объектомModelAndView
, содержащимся вModelAndViewContainer
, который управляется Spring для вашего запроса. Таким образом, то, что вы добавляете здесь, также будет доступно позже.Загвоздка: похоже, что
ModelAttribute
имеет приоритет над атрибутами модели, поэтому он не перезаписывается моделью атрибуты, добавляемые к объектуModelAndView
. На самом деле Он записывается в вашModelAndView
объект, перезаписывая ваш"task"
атрибут. Помните, что если вы не задаете атрибутvalue
для аннотации@ModelAttribute
, он использует тип аргумента, чтобы дать ему имя. Например:,Task
==>"task"
,List<Task
==>taskList
, и т.д.