spring mvc one init binder适用于所有控制器

时间:2014-01-16 14:53:54

标签: java spring spring-mvc spring-mvc-initbinders

我有5个控制器,我想向所有人注册InitBinder

我知道我可以将这些代码添加到每个代码中。

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

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

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

我使用带有java 1.6的spring 3.1.1。

2 个答案:

答案 0 :(得分:2)

实施PropertyEditorRegistrar,注册所有自定义PropertyEditors。然后在您的配置中添加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. 参考指南link

答案 1 :(得分:0)

尽管最初的问题是关于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进行工作,但是缺少设置Validator的功能。结果,用@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
    ...