Разрешить Spring иметь несколько реализаций WebMvcConfigurer в разных банках - PullRequest
0 голосов
/ 20 мая 2019

При использовании Spring Web, в данном случае для конечных точек отдыха и Spring Boot 2, я могу настроить перехватчики для моего приложения, используя интерфейс WebMvcConfigurer:

@Configuration
public class SpringWebConfig implements WebMvcConfigurer
{
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new MyInterceptor).addPathPatterns("/api/endpoint/**");
    }
}

Я добавил этот перехватчик в большинство своих приложений в автоматическом режиме, выполнив следующие действия:

  1. Создайте «общую банку» и поместите вышеуказанный интерфейс в пакет
    com.company.api.
  2. В каждом приложении добавьте пакет com.company.api в Сканирование API.

Этот общий пакет также содержит классы Interceptor и служебные классы, чтобы этот перехватчик работал, поэтому добавление этого общего jar автоматически добавит перехватчик ко всем операциям в приложении, что аналогично понятию самого Spring. делает: добавление зависимостей изменяет конфигурацию Spring по умолчанию.

Проблема, с которой я сталкиваюсь сейчас, заключается в том, что этот подход не может быть расширен до второго перехватчика во втором банке, потому что я уже использовал реализацию WebMvcConfigurer. и я не могу иметь два.

Я думал о том, чтобы, возможно, использовать какой-то шаблон составного-конфигуратора, в котором мы перебираем каждый конфигуратор, собираем все перехватчики, а затем добавляем их один раз, но, к сожалению, Spring не позволяет этого. Какие у меня варианты?

В настоящее время я выбрал дублирование интерфейса WebMvcConfigurer в каждом приложении, в котором оно требуется. Мне грустно, когда что-то меняется, и мне приходится менять один и тот же фрагмент кода в каждом приложении.

Ответы [ 2 ]

1 голос
/ 01 июня 2019

Если я правильно понимаю ваш вопрос, в основном вы хотите определить некоторые общие Interceptors в нескольких JAR-файлах, чтобы приложение могло активировать эти Interceptors, просто включив эти JAR-файлы в свое приложение?

Я думал о том, чтобы использовать какой-нибудь композитный конфигуратор шаблон, где мы перебираем каждый конфигуратор, собираем все перехватчики, а затем добавить их один раз, но, к сожалению, Spring не позволяет этого. Какие у меня варианты?

Хорошо, если реализация A возвращает реестр только с перехватчиком A, и реализация B возвращает реестр только с перехватчиком B, будет весной объединить оба реестра в один супер реестр, содержащий оба A и B, или он просто выберет один, или он выдаст ошибку, не было уникального определения бина?

На самом деле, Spring уже реализовал эту функцию . Когда имеется несколько WebMvcConfigurer bean-компонентов, Spring просто зацикливает их один за другим и вызывает их методы конфигурации. Таким образом, конечный результат состоит в том, что InterceptorRegistry будет содержать все перехватчики.

Если клиентскому приложению нужно активировать только определенные WebMvcConfigurer, оно может просто исключить те JAR-файлы, содержащие WebMvcConfigurer, которые им не нужны.

Чтобы развить эту идею, позволяющую приложению контролировать, какие Interceptors активировать вплоть до уровня перехватчика, вы можете даже сделать следующее в каждом общем JAR:

@Configuration
public class SpringWebConfig implements WebMvcConfigurer {

    //Make sure the HandlerInterceptor implementation in this JAR is a bean (e.g mark it as @Component)
    @Autowired
    private List<HandlerInterceptor> interceptors;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {

        for(HandlerInterceptor interceptor : interceptors){
            registry.addInterceptor(interceptor).addPathPatterns("/api/endpoint/**");
        }
    }
}

В клиентском приложении используйте includeFilters / excludeFilters в @ComponentScan, чтобы настроить, какие перехватчики включить. Например, чтобы отключить определенные Interceptors, вы можете сделать:

@ComponentScan(
    basePackages = {"com.company.api"},
    excludeFilters={
         @ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE, value=com.company.common.jar1.Inteceptor1.class) ,
         @ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE, value=com.company.common.jar2.Inteceptor1.class)
    })
1 голос
/ 31 мая 2019

Если я правильно понимаю вашу проблему, вы не хотите реализовывать все методы WebMvcConfigurer в каждом приложении.Вы просто хотите добавить соответствующие перехватчики и покончить с этим.

Мой подход заключается в создании AbstractWebMvcConfigurerImpl путем реализации WebMvcConfigurer в модуле Common.Просто оставьте аннотацию addInterceptors() и реализуйте другие методы.Затем вы можете расширить эту абстрактную реализацию в каждом проекте Spring Boot и просто переопределить метод addInterceptors() в соответствии с вашими потребностями.

Кроме того, вы можете иметь столько реализаций WebMvcConfigurer, сколько захотите в проекте Spring.Таким образом, если вам нужно определить некоторые общие перехватчики в модуле Common, вы можете также расширить AbstractWebMvcConfigurerImpl в общем модуле.

Обратите внимание, что все ваши реализации AbstractWebMvcConfigurerImpl должны быть аннотированы @Configuration

...