Можно ли вручную установить объект команды в методе @RequestMapping перед привязкой Spring?
-
21-08-2019 - |
Вопрос
У меня есть JSP, в котором есть форма Spring.Объект команды формы добавляется в контроллер перед визуализацией JSP.Spring привязывает форму в JSP к этому командному объекту и будет правильно обрабатывать ее при отправке НОВОГО экземпляра.
Однако я хотел бы сохранить объект команды через DWR (который также работает правильно), а затем отправить форму контроллеру.В момент отправки формы контроллеру объект команды больше не является новым объектом, а является постоянным объектом, который необходимо обновить.Здесь я хочу, чтобы элементы формы автоматически привязывались к объекту команды и обновлялись посредством привязки, но они не привязываются.
ПРОСТОЙ пример:Я добавлю новый Task
к ModelMap
, чтобы форма Spring была привязана к этому командному объекту.Однако вместо подачи нового Task
, я буду настаивать на этом новом Task
через DWR, который вернет идентификатор, а затем продолжит редактирование задачи перед отправкой формы контроллеру.
Класс контроллера
@Controller
public class ProjectController {
/**
* This adds the "task" command object to the session attributes and loads
* the initial form.
*/
@RequestMapping(value="/project", method=RequestMethod.GET)
public String setupForm(@RequestParam(value="id", required=true) String id,
HttpServletRequest request, ModelMap modelMap) {
modelMap.addAttribute("project", projectRepo.get(id));
modelMap.addAttribute("task", new Task());
return "/project/task";
}
/**
* This processes the form submit, and should update the Task.
*/
@RequestMapping(value="/project/task/update", method=RequestMethod.POST)
public String updateTask(@ModelAttribute(value="task") Task task,
@RequestParam(value="taskId") String taskId,
HttpServletRequest request, ModelMap modelMap) {
// BEFORE binding the parameters to the command object (task),
// I want to assign the command object as the one already persisted.
task = taskRepo.get(taskId);
// NOW, I want the request parameters to be bound to the task command object.
// HOW ?????????
// Persist the changes.
taskRepo.merge(task);
// BACK to the setupForm method/form view
return "/project?id=" + task.getProject().getId();
}
}
Весенняя форма
<form:form commandName="task" method="post" action="/project/task/update" id="taskForm">
<form:hidden path="id" id="task.id"/>
<form:input path="name" id="task.name"/>
<!-- DWR will save the task (save and continue), then will return the id. -->
<!-- After saved, the user can still change the name,
then submit the form for processing by the controller -->
</form:form>
Можно ли установить объект команды, связанный с Spring, в постоянный объект до того, как произойдет какая-либо привязка после отправки?
Решение
На самом деле есть лучший способ сделать это с помощью аннотаций.
Создайте метод ModelAttribute, который возвращает нужный объект команды из репозитория.
@ModelAttribute("task")
public Task task(@RequestParam(value = "id", required = true) String id) {
return taskRepo.get(taskId);
}
Затем просто добавьте ModelAttribute в метод отправки формы.
@RequestMapping(value="/project/task/update", method=RequestMethod.POST)
public String updateTask(@ModelAttribute(value="task") Task task,
HttpServletRequest request, ModelMap modelMap) {
taskRepo.merge(task);
...
}
Другие советы
Похоже, что при использовании @ModelAttribute
для доступа к объекту команды, привязка происходит до того, как вы получите доступ к объекту команды.Чтобы установить для этого командного объекта то, что вы хотите, прежде чем привязывать параметры запроса из формы, просто передайте идентификатор атрибута и получите его из базы данных, а затем привяжите параметры WebRequest.
В методе POST
@RequestMapping(value="/project/task/update", method=RequestMethod.POST)
public String updateTask(@ModelAttribute(value="task") Task task,
@RequestParam(value="taskId") String taskId,
HttpServletRequest request, ModelMap modelMap) {
// BEFORE binding the parameters to the command object (task),
// I want to assign the command object as the one already persisted.
task = taskRepo.get(taskId);
// NOW, I want the request parameters to be bound to the task command object.
WebRequestDataBinder binder = new WebRequestDataBinder(task);
ServletWebRequest webRequest = new ServletWebRequest(request);
binder.bind(webRequest);
// Persist the changes.
taskRepo.merge(task);
// BACK to the setupForm method/form view
return "/project?id=" + task.getProject().getId();
}
А Документация Spring 2.5.x WebRequestDataBinder
здесь вы можете найти Юрген Хеллер пример «привязки данных вручную» для этого типа приложения.
MyBean myBean = new MyBean();
// apply binder to custom target object
WebRequestDataBinder binder = new WebRequestDataBinder(myBean);
// register custom editors, if desired
binder.registerCustomEditor(...);
// trigger actual binding of request parameters
binder.bind(request);
// optionally evaluate binding errors
Errors errors = binder.getErrors();
...