我正在从Spring 2.5升级到Spring 3.2。我有一个以前扩展CancellableFormController
的MVC控制器。它分别声明了initBinder()
和onBind()
方法。我重构了Controller以使用@Controller
注释,并将重写的initBinder()
方法切换为使用Spring MVC 3注释@initBinder
。
我的具体问题是,在Spring MVC 3中,从Spring 2.5升级,如何重构被覆盖的onBind()
方法以使用注释等价物?现有方法的签名是:
@Override
protected void onBind(HttpServletRequest request, Object command, BindException errors) throws Exception {
MyCommand cmd = (MyCommand) command;
....
}
我考虑过使用@initBinder()
并将之前的代码放在onBind()
这个带注释的方法中。但我在这里的困惑是:
@initBinder
带注释的方法获取Command对象的句柄。我可以将它声明为方法签名中的另一个参数,Spring MVC框架将确保我得到一个副本吗?似乎在旧onBind()
方法中已经创建了Command对象(通过formBackingObject
方法)。我可以安全地假设使用@initBinder
方法时也是如此吗?
感谢任何人的一些见解。我正在努力加快Spring MVC流程的速度!
我现有的@initBinder
方法签名类似于:
@InitBinder
protected void initBinder(WebDataBinder binder) {
// register custom editor here.. etc
}
我希望我可以这样做:
@InitBinder
protected void initBinder(WebDataBinder binder, MyCommand cmd) {
// register custom editor here.. etc
}
这是使用注释升级cancellableformcontroller onBind()方法的标准最佳实践方法吗?
@InitBinder("myCommand")
protected void onBind(WebDataBinder binder) throws Exception {
MyCommand cmd = (MyCommand) binder.getTarget();
.... // do whatever was required here...
}
请参阅下面我对zeroflag的评论。使用onBind()中包含的相同逻辑创建一个私有方法,然后在onSubmit()注释方法(POST / GET)中验证命令对象后,调用现在已不存在的onBind()方法,将Command对象作为一个传递给参数。如下所示:
@RequestMapping(method=RequestMethod.POST)
public ModelAndView onSubmit(@ModelAttribute("myCommand") MyCommand cmd, BindingResult result, <any other params> {
new MyCommandValidator().validate(cmd, result);
if (result.hasErrors()) {
return new ModelAndView("context");
}
onBind(cmd, <any other params>);
... // do business stuff
}
这似乎是一个丑陋的解决方法,对我的具体情况来说是好的。
答案 0 :(得分:1)
您可以使用binder.getTarget()
访问命令对象。为控制器方法的每个模型参数调用@InitBinder
。我们假设以下代码
@RequestMapping("/somePath")
public String myMethod(@ModelAttribute("user") User user,
@ModelAttribute("info") Info info) {
然后,您的initBinder
方法至少被调用两次:对于User
对象和Info
对象。要仅为特定对象调用它,请添加模型名称:
@InitBinder("user")
这样只会为User
对象调用它。但请注意,该方法可能仍会被多次调用,即使目标对象为空也是第一次。
如果您想确保某些字段未自动设置,则可以在setDisallowedFields()
方法中使用initBinder
。
如果您想进行一些验证,那么让JSR 303(Bean Validation)完成这项工作。
根据您的想法,控制器中的@ModelAttribute
方法可能是一个解决方案:
@ModelAttribute("user")
public User createUser(HttpServletRequest request /*or whatever*/) {
User user = new User();
//check some parameters and set some attributes
return user;
}
在绑定发生之前创建用户对象。
最后一个解决方案可以是命令对象的消息或类型转换器,它可以根据请求创建对象。这实际上与上面的示例相似,但与控制器无关,并且对使用转换器创建的对象没有绑定。