【问题标题】:@InitBinder using command object in property editors…@InitBinder 在属性编辑器中使用命令对象...
【发布时间】:2012-05-23 04:57:11
【问题描述】:

我正在将应用程序从 Spring 2.0.7 迁移到 3.1.1,但遇到了 initBinder 问题。我们以前的方法看起来像

protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception {
    MyCommand command = (MyCommand)binder.getTarget();
    binder.registerCustomEditor(CustomerCard.class, createEditorFromCommand(command));
}

PropertyEditor 使用目标的位置。当我将它设置为带注释的 Controller 时不再调用此方法,因此我添加了 @InitBinder 注释:

@InitBinder
protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception {
    MyCommand command = (MyCommand)binder.getTarget();
    binder.registerCustomEditor(CustomerCard.class, createEditorFromCommand(command));
}

不幸的是,binder.getTarget() 只是一些默认对象。 @InitBinder 的文档还指出我也无法将该命令作为参数:

这样的 init-binder 方法支持所有 {@link RequestMapping} 支持,除了命令/表单对象和 对应的验证结果对象。

这样做的正确方法是什么?

【问题讨论】:

    标签: spring spring-3


    【解决方案1】:

    聚会可能有点晚了,但仍然 - 这是一种在 @InitBinder 方法中引用模型(命令)对象的方法:

    @InitBinder("commandName")
    public void initBinder(WebDataBinder binder) throws Exception {
       CommandClass command = (CommandClass) binder.getTarget();
       binder.registerCustomEditor(Some.class, new SomeEditor(command.getOptions());
    }
    
    @ModelAttribute("commandName")
    public OrderItem createCommand(HttpServletRequest request) {
       return new CommandClass();
    }
    

    使用@InitBinder("something") 而不仅仅是@InitBinder 可能是个好主意。这样@InitBinder 就不会被多次调用,而只会在遇到配置的对象时调用。

    【讨论】:

      【解决方案2】:
      @RequestMapping
      // binder will return MyCommand on getTarget()
      public void handleMyCommand(MyCommand c) {  
       ...
      }
      
      // initialize command before handleMyCommand method call
      @ModelAttribute
      public MyCommand initializeMyCommand() {
         // perform initialization.
      }
      
      @InitBinder
      protected void initBinder(WebDataBinder binder) {
         MyCommand c  = (MyCommand) binder.getTarget();
         binder.registerCustomEditor(CustomerCard.class, createEditorFromCommand(c));
      }
      

      但是,由于命令是统一化的 ¿ 为什么不直接调用 createEditorFromCommand(new MyCommand())

      【讨论】:

      • 该命令不应该未初始化,就是这样。我认为我的问题是我将旧的 Spring 类层次结构与注释相结合。我现在有点介于两者之间,试图一次转移到一个控制器的新方式。我有一个旧的formBackingObject,但由于 Spring 不再调用这个,我用@ModelAttribute 做了一个新方法,然后调用这个旧的formBackingObject。但是,@ModelAttribute 对我从该方法返回的命令对象没有做任何事情,对吗?还有其他方法可以“注册”命令吗?
      • 要初始化命令,请在方法上使用@ModelAttribute。我只是用示例编辑答案。
      • 我做到了。似乎问题在于initBinder 被多次调用。除了上面的@ModelAttribute 方法之外,我还有一个返回 void 的方法,它采用模型映射并在其中设置很多东西。似乎一切都调用了 initBinder。我让它在目标上进行 instanceof-check in 工作,但它看起来很老套……?
      • 是的,每次命令上的绑定进程启动时都会调用 initBinder,因此像 handle(Command1 c1, Command2 c2) 这样的处理程序将调用 initBinder 两次。 PropertyEditor 将实例类从文本转换为文本。我认为您不会根据实例数据选择 PE,¿ 为 CustomCard 做一个可以处理所有可能性并简单地在 initBinder 方法上注册它们的唯一 PE 可能会更好?
      【解决方案3】:
      @InitBinder
      protected void initBinder(WebDataBinder binder) {
        MyCommand command = (MyCommand)binder.getTarget();
        binder.registerCustomEditor(CustomerCard.class, createEditorFromCommand(command));
      }
      

      【讨论】:

      • 该代码给出了同样的问题。该命令只是一个Object 而不是我注册的命令。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多