【发布时间】:2012-10-11 06:07:23
【问题描述】:
我见过很多关于simpleFormcontroller 工作原理的例子。
但我还是有些困惑。
我想知道formBackingObject()、referenceData()、onSubmit() 方法何时被调用?
我不知道这些方法的具体工作流程?
谁能解释一下?
【问题讨论】:
标签: spring spring-mvc controller
我见过很多关于simpleFormcontroller 工作原理的例子。
但我还是有些困惑。
我想知道formBackingObject()、referenceData()、onSubmit() 方法何时被调用?
我不知道这些方法的具体工作流程?
谁能解释一下?
【问题讨论】:
标签: spring spring-mvc controller
工作流程如下,由AbstractFormController类控制-
- 控制器收到新表单的请求(通常是 GET)。
- 调用 formBackingObject(),默认情况下会返回已配置的 commandClass 实例(参见超类公开的属性),但也可以被覆盖例如从数据库中检索一个对象(需要使用表单进行修改)。
- 调用 initBinder(),它允许您为命令类的某些字段(通常是非原始或非字符串类型的属性)注册自定义编辑器。这将为这些属性值呈现适当的字符串,例如特定于语言环境的日期字符串。
- 仅当 bindOnNewForm 设置为 true 时,才会应用 ServletRequestDataBinder 以使用初始请求参数填充新表单对象,并调用 onBindOnNewForm(HttpServletRequest, Object, BindException) 回调方法。注意:此时不应用任何定义的验证器,以允许部分绑定。但是请注意,通过 initBinder() 应用的任何 Binder 自定义(例如 DataBinder.setRequiredFields(String[]) 仍然适用。因此,如果使用 bindOnNewForm=true 和 initBinder() 自定义)验证字段而不是使用验证器,如果只为新表单填充一些字段,则错误对象中缺少字段可能会出现一些绑定错误。任何显示绑定错误的视图(JSP 等)都需要要智能,在这种情况下,请考虑是显示初始表单视图还是显示后续发布结果,跳过前者的错误显示。
- 调用 showForm() 以返回应呈现的视图(通常是呈现表单的视图)。此方法必须在子类中实现。
- showForm() 实现将调用 referenceData(),您可以实现它以提供您在编辑表单时可能需要的任何相关参考数据(例如您要让用户从中选择一个的语言环境对象)。
- 模型被暴露,视图被渲染,让用户填写表单。
- 控制器接收表单提交(通常是 POST)。要使用不同的方式检测表单提交,请覆盖 isFormSubmission 方法。
- 如果未设置 sessionForm,则调用 formBackingObject() 来检索表单对象。否则,控制器会尝试查找已经绑定在会话中的命令对象。如果找不到对象,它会调用 handleInvalidSubmit - 默认情况下 - 尝试创建新的表单对象并重新提交表单。
- ServletRequestDataBinder 被应用以使用当前请求参数填充表单对象。
- 调用 onBind(HttpServletRequest, Object, Errors) 允许您在绑定之后但验证之前进行自定义处理(例如,手动将请求参数绑定到 bean 属性,以供验证器查看) .
- 如果设置了 validateOnBinding,将调用已注册的验证器。 Validator 将检查表单对象的属性,并通过给定的 Errors 对象注册相应的错误。
- 调用 onBindAndValidate() 允许您在绑定和验证之后进行自定义处理(例如手动绑定请求参数,并在验证器之外验证它们)。
- 调用 processFormSubmission() 来处理提交,无论是否存在绑定错误。此方法必须在子类中实现。
有关更多详细信息和图表表示以了解流程,您可以参考以下链接 -
【讨论】:
SimpleFormController 自 Spring 3.0 起已弃用
在 Spring 3.0 中,使用一个控制器和两种方法用于创建过程(第三种方法用于显示页面)。典型的样子是这样的:
/**
* Shows a form for car creation.
*/
@RequestMapping(params = "form", method = RequestMethod.GET)
public ModelAndView createForm() {
ModelMap uiModel = new ModelMap();
uiModel.addAttribute("carCreateFormBackingObject", new CarCreateFormBackingObject()); //formBackingObject - often called command object
uiModel.addAttribute("manufactureres", this.manufactureresDao.readAll()); //referenceData
return new ModelAndView("car/create", uiModel);
}
/**
* Creates the car and redirects to its detail page.
*
*/
@RequestMapping(method = RequestMethod.POST)
public ModelAndView create(final @Valid CarCreateFormBackingObject carCreateFormBackingObject,
final BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
ModelMap uiModel = new ModelMap();
uiModel.addAttribute("carCreateFormBackingObject", carCreateFormBackingObject);
uiModel.addAttribute("manufactureres", this.manufactureresDao.readAll()); //referenceData
return new ModelAndView("car/create", uiModel);
}
Car car = this.carService.create(carCreateFormBackingObject.name, ...);
return new ModelAndView(new RedirectView("/cars/" + car.getId(), true)); //redirect to show page
}
我还想知道 formBackingObject(),refernceData() 方法是由谁以及何时自动调用的?
回到你的问题“我仍然想知道 formBackingObject(),refernceData() 方法是由谁以及何时自动调用的?”
所有这些方法都由SimpleFormController(及其超类AbstractFormController)调用,遵循模板-方法-模式。 - SimpleFormController 在该流程的一些钩子中定义流程和您的具体子类“插件”以获得业务价值。
formBackingObject 在控制器需要处理提交 (POST) 或为初始“新”视图构建 Command 对象时由 AbstractFormController 调用。
referenceData 在需要为视图构建模型时始终调用AbstractFormController。
【讨论】:
formBackingObject() 方法,用于在渲染页面之前执行一些操作。即类似于 HTML 组件中的默认值。
refereceData() 方法,用于在表单中添加参考数据,即填充下拉列表
OnSubmit() 方法,在您提交表单时调用。
但是,如果您使用的是 Spring 3.0 使用注释遵循以下方法
@RequestMapping(value = "/index.htm", method = RequestMethod.GET)
public String showLogin() {
return "user/login";
}
这将与 formBackingObject 相同。并在此方法中使用 modelMap() 并添加参考数据。
添加方法的方式与 method = POST 相同,与 OnSubmit() 相同
【讨论】:
rfe 后续链接
阅读Workflow..你可以简单理解你的疑惑..
【讨论】:
FormBackingObjectMethod()---> @RequestMapping(requestMethod.GET) 而第一次显示在屏幕上的表单 formBackingObject 是原因
initBinder()---> 通常用于假设你想要的日期字段应该是例如(自定义日期示例:dd**MM***yyyy)需要意味着使用 initBinder 方法
onSubmit() -->@RequestMapping(requestMethod.POST) 在提交表单时调用 onSubmit() 方法
希望对你有帮助
【讨论】: