允许Spring在不同的jar中具有多个WebMvcConfigurer实现

时间:2019-05-20 07:31:26

标签: java spring-boot spring-mvc interceptor spring-web

在使用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. 创建一个“ common-jar”,并将上面的界面放在包中
    com.company.api
  2. 在每个应用中,将包com.company.api添加到 api扫描。

此公共包还包含使该拦截器正常工作的Interceptor和实用程序类,因此,实际上,添加此common-jar会自动将拦截器添加到应用程序中的所有操作中,这与Spring本身的概念类似确实:添加依赖项会更改Spring的默认配置。

我现在面临的问题是该方法无法扩展到第二个jar中的第二个拦截器,因为我已经使用了WebMvcConfigurer实现。我不能有两个。

我正在考虑使用某种复合配置器模式,在该模式中,我们遍历每个配置器,收集所有拦截器,然后将它们添加一次,但是不幸的是Spring不允许这样做。我有什么选择?

当前,我采用的方法是在每个需要它的应用程序中复制WebMvcConfigurer界面。当事情发生变化时,我感到很难过,而且我必须在每个应用程序中都更改相同的代码段。

2 个答案:

答案 0 :(得分:1)

如果我正确理解了您的问题,则您不想在每个应用程序中实现WebMvcConfigurer的所有方法。您只想添加相关的拦截器并完成它。

我的方法是通过在AbstractWebMvcConfigurerImpl模块中实现WebMvcConfigurer来创建Common。只需保留addInterceptors()抽象并实现其他方法即可。然后,您可以在每个Spring Boot项目中扩展该抽象实现,并根据需要重写addInterceptors()方法。

另外,在Spring项目中,您可以根据需要拥有WebMvcConfigurer的实现。因此,如果需要在Common模块中定义一些公共拦截器,则也可以在公共模块中扩展AbstractWebMvcConfigurerImpl

请注意,您对AbstractWebMvcConfigurerImpl的所有实现都应使用@Configuration

进行注释

答案 1 :(得分:0)

如果我正确理解了您的问题,基本上您想在多个JAR中定义一些常见的Interceptors,以便应用程序可以通过简单地将这些JAR包含在其应用程序中来激活这些Interceptors

  

我正在考虑也许使用某种复合配置器   我们遍历每个配置器,收集所有拦截器的模式   然后将它们添加一次,但是不幸的是Spring不允许这样做。   我有什么选择?

     

好吧,如果实现A返回仅包含拦截器A的注册表,   并且实现B返回仅包含拦截器B的注册表,   春天将两个注册表合并为一个包含两个注册表的超级注册表   A和B,或者只是选择一个,还是会抛出一个错误   没有唯一的bean定义吗?

实际上,Spring已经实现了this feature。当有多个WebMvcConfigurer bean时,Spring只需loop them one by one并调用其配置方法。因此最终结果是InterceptorRegistry将包含所有拦截器。

如果客户端应用程序仅需要激活某些WebMvcConfigurer,则可以简单地排除那些包含其不需要的WebMvcConfigurer的JAR。

为了使这个想法更进一步,使应用程序可以控制将哪个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)
    })