Пружинный 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 и соединить все вместе.

связи

  1. PropertyEditorRegistrar javadoc
  2. ConfigurableWebBindingInitializer javadoc
  3. Ссылка на справочник

Хотя первоначальный вопрос касался 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
    ...
Другие вопросы по тегам