I have 5 controllers and i would like to register an InitBinder
to all of them.
I know i can add this code to each of them.
@InitBinder
public void initBinder(WebDataBinder binder)
{
binder.registerCustomEditor(StringWrapper.class, new StringWrapperEditor());
}
But i would like to define it only once (even create a bean of StringWrapperEditor
and use it instead of creating new every time.)
I searched SO and some other places but didn't find any answear. Is it even possible?
Im using spring 3.1.1 with java 1.6.
Implement a PropertyEditorRegistrar
which registers all your custom PropertyEditors
. Then in your configuration add a ConfigurableWebBindingInitializer
which you hookup with the created PropertyEditorRegistrar
and hook it to your HandlerAdapter
.
public class MyPropertyEditorRegistrar implements PropertyEditorRegistrar {
public void registerCustomEditors(PropertyEditorRegistry registry) {
registry.registerCustomEditor(StringWrapper.class, new StringWrapperEditor());
}
}
If you have a <mvc:annotation-driven />
tag in your configuration, the problem is that with this tag you cannot add the WebBindingInitializer
to the adapter next to that there is already a ConfigurableWebBindingInitializer
added to the pre-configured HandlerAdapter. You can use a BeanPostProcessor
to proces and configure the 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());
}
}
}
}
Requires a bit of work but it is doable. You could also implement your own WebBindingInitializer
.
If you don't have the tag you can simply manually configure a RequestMappingHandlerAdapter
and wire everything together.
Links
Though the initial question was about Spring 3.1, the following might be useful for those who use newer Spring versions.
One possible option is to move your @InitBinder to @ControllerAdvice, for example
@ControllerAdvice
class InitBinderControllerAdvice {
@InitBinder
fun initBinder(dataBinder: WebDataBinder) {
dataBinder.registerCustomEditor(
MLQueryOutputFormat::class.java,
StringToMLQueryOutputFormat()
)
dataBinder.registerCustomEditor(
IDatabaseOps.SortDirection::class.java,
StringToSortDirection()
)
}
}
Regarding ConfigurableWebBindingInitializer, even though it's quite a powerful thing, it requires additional configuration in terms of validation and etc. So pay attention to detail once implementing it. For instance, the following code does the job as per InitBinder, but lacks setting a Validator. As a result, the validation of the rest controller param annotated with @Validated didn't work:
@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
}
}
To add validation, one could do the following:
@Bean
fun configurableWebBindingInitializer(
@Qualifier("defaultValidator") validator: Validator
): ConfigurableWebBindingInitializer {
val initializer = ConfigurableWebBindingInitializer()
initializer.validator = validator
...
来源:https://stackoverflow.com/questions/21165135/spring-mvc-one-init-binder-for-all-controllers