是否可以在Spring绑定之前在@RequestMapping方法中手动设置命令对象?

时间:2009-05-13 17:35:17

标签: spring jsp spring-mvc dwr

我有一个包含Spring表单的JSP。在呈现JSP之前,将在控制器中添加表单的命令对象。 Spring将JSP中的表单绑定到此命令对象,并在提交新实例时正确处理它。

但是,我想通过DWR(也可以正常工作)保持命令对象,然后将表单提交给控制器。在将表单提交给控制器时,命令对象不再是新对象,而是需要更新的持久对象。这是我希望表单元素自动绑定到命令对象并通过绑定更新的地方,但它们没有被绑定。

SIMPLE示例:我将向Task添加一个新的ModelMap,以便Spring表单将绑定到该命令对象。但是,我不会提交新的Task,而是通过DWR保留新的Task,这将返回ID,然后在将表单提交给控制器之前继续编辑任务。

控制器类

@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();
    }
}

Spring Form

<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 个答案:

答案 0 :(得分:3)

使用注释实际上有更好的方法。

创建一个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 :(得分:1)

当使用@ModelAttribute访问命令对象时,似乎在您访问命令对象之前发生了绑定。为了在从表单绑定请求参数之前将该命令对象设置为您想要的,只需传入属性的id并从数据库中获取它,然后绑定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 documentation of WebRequestDataBinder是您可以找到Juergen Hoeller's此类应用程序的'手动数据绑定'示例。

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();
...