Можно ли вручную установить объект команды в методе @RequestMapping перед привязкой Spring? - PullRequest
1 голос
/ 13 мая 2009

У меня есть JSP, в котором есть форма Spring. Командный объект формы добавляется в контроллер до визуализации JSP. Spring связывает форму в JSP с этим объектом команды и будет правильно обрабатывать ее при отправке нового экземпляра.

Однако я хотел бы сохранить объект команды через DWR (который также работает правильно), а затем отправить форму контроллеру. В тот момент, когда форма отправляется в контроллер, объект команды больше не является новым объектом, а является постоянным объектом, который необходимо обновить. Здесь я хочу, чтобы элементы формы автоматически связывались с объектом команды и обновлялись через связывание, но они не связаны.

SIMPLE Пример: я добавлю новый 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, постоянным объектом до того, как произойдет привязка после отправки?

Ответы [ 2 ]

3 голосов
/ 19 мая 2009

На самом деле есть лучший способ сделать это с помощью аннотаций.

Создайте метод 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);
    ...
}
1 голос
/ 15 мая 2009

Похоже, что при использовании @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();
...
...