java - 允许 Spring 在不同的 jars 中有多个 WebMvcConfigurer 实现

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

当使用 Spring Web 时,在这种情况下,对于 rest 端点和使用 Spring Boot 2,我可以通过实现 WebMvcConfigurer 接口(interface)为我的应用程序配置拦截器:

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

我通过执行以下操作以自动方式将此拦截器添加到我的大多数应用程序中:

  1. 创建一个“common-jar”,把上面的接口(interface)放到package下
    com.company.api
  2. 在每个应用程序中,将包 com.company.api 添加到 api 扫描。

这个通用包还包含Interceptor和实用程序类来使这个拦截器工作,所以实际上,添加这个common-jar会自动将他的拦截器添加到应用程序中的所有操作中,这与Spring本身的概念类似do: 添加依赖会改变 Spring 的默认配置。

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

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

目前,我采用的方法是在每个需要它的应用程序中复制 WebMvcConfigurer 接口(interface)。当某些事情发生变化时我会感到难过,我必须在每个应用程序中更改相同的代码片段。

最佳答案

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

I was thinking about maybe using some kind of composite-configurer pattern where we loop over every configurer, collect all interceptors, and then add them once, but unfortunately Spring doesn't allow this. What are my options?

Well, if implementation A returns a registry with only interceptor A, and implementation B returns a registry with only interceptor B, would spring combine both registries into one super registry containing both A and B, or would it just pick one, or would it throw an error that there was no unique bean definition ?

其实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/**");
        }
    }
}

在客户端应用程序中,使用 @ComponentScan 中的 includeFilters/excludeFilters 来自定义要包含哪些拦截器。例如,要禁用某些 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)
    })

关于java - 允许 Spring 在不同的 jars 中有多个 WebMvcConfigurer 实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56216178/

相关文章:

java - 为什么我的应用程序无法处理我的 Intent ?

java - 如何在 BIRT 报告中绘制图形或自定义设计的图表?

postgresql - Spring Boot 2.2.2 和 "hibernate.hbm2ddl.auto=(create|create-drop|update|validate)"不工作

java - Spring Boot Autowiring 空值

java - 如何在未使用 XML 配置文件配置的 Spring 应用程序中激活 JSR-250 注释?

java - Spring Security 用户身份验证不起作用

java - HTTP 状态 400 - 客户端发送的请求在语法上不正确。 - 在使用 Hibernate 的 Spring MVC Web 应用程序中

java - 我无法使用 spring security 登录

java - 如何删除滑动窗口中的重复项 - Apache Beam

java - 启动时的 Liquibase 迁移无法使用 Spring-Boot