Пружинный MVC один инициатор связующего для всех контроллеров
У меня есть 5 контроллеров, и я хотел бы зарегистрировать InitBinder
всем им.
Я знаю, что могу добавить этот код к каждому из них.
@InitBinder
public void initBinder(WebDataBinder binder)
{
binder.registerCustomEditor(StringWrapper.class, new StringWrapperEditor());
}
Но я хотел бы определить это только один раз (даже создать бин StringWrapperEditor
и использовать его вместо создания нового каждый раз.)
Я искал ТАК и некоторые другие места, но не нашел ответа. Это вообще возможно?
Я использую пружину 3.1.1 с Java 1.6.
1 ответ
Реализовать 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
обработать и настроить бин.
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
и соединить все вместе.
связи
Хотя первоначальный вопрос касался 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
...