Spring MVC 一个用于所有控制器的初始化活页夹



我有 5 个控制器,我想为所有控制器注册一个InitBinder

我知道我可以将此代码添加到他们每个人中。

@InitBinder
public void initBinder(WebDataBinder binder)
{
    binder.registerCustomEditor(StringWrapper.class, new StringWrapperEditor());
}

但我只想定义它一次(甚至创建一个 StringWrapperEditor bean 并使用它而不是每次都创建新的。

我搜索了SO和其他地方,但没有找到任何answear。甚至可能吗?

我使用 spring 3.1.1 和 java 1.6。

虽然最初的问题是关于Spring 3.1的,但以下内容可能对使用较新Spring版本的人有用。

例如,一种可能的选择是将@InitBinder移动到@ControllerAdvice

@ControllerAdvice
class InitBinderControllerAdvice {
    @InitBinder
    fun initBinder(dataBinder: WebDataBinder) {
        dataBinder.registerCustomEditor(
            MLQueryOutputFormat::class.java,
            StringToMLQueryOutputFormat()
        )
        dataBinder.registerCustomEditor(
            IDatabaseOps.SortDirection::class.java,
            StringToSortDirection()
        )
    }
}

关于 ConfigurableWebBindingInitializer,尽管它是一个非常强大的功能,但它需要在验证等方面进行额外的配置,因此一旦实现它,请注意细节。例如,以下代码按照 InitBinder 完成工作,但缺少设置验证器。结果,使用 @Validated 注释的其余控制器参数的验证不起作用:

@Configuration
class WebMvcConfig {
    @Bean
    fun configurableWebBindingInitializer(): ConfigurableWebBindingInitializer {
        val initializer = ConfigurableWebBindingInitializer()
        initializer.propertyEditorRegistrars = arrayOf(
            PropertyEditorRegistrar {
                it.registerCustomEditor(
                    MLQueryOutputFormat::class.java,
                    StringToMLQueryOutputFormat()
                )
            }, PropertyEditorRegistrar {
                it.registerCustomEditor(
                    IDatabaseOps.SortDirection::class.java,
                    StringToSortDirection()
                )
            }
        )
        return initializer
    }
}

要添加验证,可以执行以下操作:

@Bean
fun configurableWebBindingInitializer(
    @Qualifier("defaultValidator") validator: Validator
): ConfigurableWebBindingInitializer {
    val initializer = ConfigurableWebBindingInitializer()
    initializer.validator = validator
    ...

实现一个注册所有自定义PropertyEditorsPropertyEditorRegistrar。然后在您的配置中添加一个ConfigurableWebBindingInitializer,您将它与创建的PropertyEditorRegistrar连接起来,并将其挂接到您的HandlerAdapter

public class MyPropertyEditorRegistrar implements PropertyEditorRegistrar {
    public void registerCustomEditors(PropertyEditorRegistry registry) {
         registry.registerCustomEditor(StringWrapper.class, new StringWrapperEditor());   
    }
}

如果您的配置中有 <mvc:annotation-driven /> 标记,则问题是使用此标记无法将WebBindingInitializer添加到适配器旁边,该适配器旁边已经有一个ConfigurableWebBindingInitializer添加到预配置的 HandlerAdapter。您可以使用BeanPostProcessor来处理和配置 Bean。

public class MyPostProcessor implements BeanPostProcessor {
    public Object postProcessBeforeInitialization(Object bean, String name) throws BeansException {
        if (bean instanceof RequestMappingHandlerAdapter) {
            WebBindingInitializer wbi = ((RequestMappingHandlerAdapter) bean).getWebBindingInitializer();
            if (wbi == null) {
                wbi = new ConfigurableWebBindingInitializer();
                ((RequestMappingHandlerAdapter) bean).setWebBindingInitializer(wbi);
            }
            if (wbi instanceof ConfigurableWebBindingInitializer) {
                ((ConfigurableWebBindingInitializer) wbi).setPropertyEditorRegistrar(new MyPropertyEditorRegistrar());
            }
        }
    }
}

需要一些工作,但这是可行的。您也可以实现自己的WebBindingInitializer

如果您没有标签,您可以简单地手动配置RequestMappingHandlerAdapter并将所有内容连接在一起。

链接

  1. PropertyEditorRegistrar javadoc
  2. ConfigurableWebBindingInitializer javadoc
  3. 参考指南链接

最新更新