You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Spring Cloud Gateway自定义网关过滤器未生效、调试无法命中及Bean定义冲突问题排查求助

解决Spring Cloud Gateway自定义过滤器不触发及Bean冲突问题

让我们一步步拆解你的问题,逐个解决:

一、先搞定Bean定义冲突的异常

你遇到的BeanDefinitionStoreException本质是重复定义了同一个Bean

  • 你的AuthorizationHeaderFilter已经标注了@Component@RefreshScope,Spring容器会自动扫描并创建这个Bean,同时@RefreshScope会生成一个ScopedProxyFactoryBean代理对象。
  • 你又在主类里用@Bean手动创建了同名的authorizationHeaderFilter,这就导致Spring无法确定用哪个实例,抛出了覆盖冲突的异常。

解决方案:直接删除主类中的@Bean定义,保留AuthorizationHeaderFilter上的@Component@RefreshScope即可。

二、解决自定义过滤器不被触发的核心问题

从你提供的日志能看出关键问题:请求实际匹配的是ReactiveCompositeDiscoveryClient_USERS-WS这个自动生成的路由,而不是你自定义的users-status-check路由!这就是过滤器完全没执行的根本原因。

1. 调整路由优先级,让自定义路由优先匹配

Spring Cloud Gateway的路由匹配规则是按order值从小到大优先匹配,自动发现的路由(比如服务注册中心生成的)默认order=0,自定义路由默认也是0。你需要给自定义路由设置更小的order值(比如-1),让它先被选中:

spring.cloud.gateway.routes[0].order=-1

2. 确认自定义过滤器工厂的命名规范

Spring Cloud Gateway对过滤器工厂的命名有约定:

  • 官方规范是类名以GatewayFilterFactory结尾(比如AuthorizationHeaderGatewayFilterFactory),这样配置文件中可以直接用前缀AuthorizationHeader引用。
  • 如果你不想修改类名,需要重写name()方法,明确指定配置中要用的过滤器名称,确保和配置里的AuthorizationHeaderFilter一致:
@Override
public String name() {
    return "AuthorizationHeaderFilter";
}

3. 排查Header Predicate的拦截影响

你的路由配置里加了Header=Authorization, Bearer (.*)这个Predicate,它会先校验请求头是否符合正则规则。如果你的请求头格式不对(比如Bearer后面没空格、拼写错误,或者token格式不匹配),路由根本不会匹配,过滤器自然不会执行。

可以先暂时注释掉这个Header Predicate,测试过滤器是否能正常触发,确认无误后再调整正则规则。

4. 完善过滤器的异常处理与日志

你的isJwtValid方法在JWT解析失败时会直接抛出异常(比如签名错误、token过期),这会导致请求中断且没有友好响应。建议添加异常捕获:

private static final Logger log = LoggerFactory.getLogger(AuthorizationHeaderFilter.class);

private boolean isJwtValid(String token) {
    try {
        String subject = Jwts.parser()
                .setSigningKey(environment.getProperty("token.secret"))
                .parseClaimsJws(token)
                .getBody()
                .getSubject();
        return subject != null && !subject.isEmpty();
    } catch (JwtException | IllegalArgumentException e) {
        log.error("Failed to validate JWT token", e);
        return false;
    }
}

同时在apply方法开头添加日志,方便快速确认过滤器是否执行:

@Override
public GatewayFilter apply(Config config) {
    return ((exchange, chain) -> {
        log.debug("Processing request with AuthorizationHeaderFilter: {}", exchange.getRequest().getPath());
        ServerHttpRequest request = exchange.getRequest();
        // 原有逻辑...
    });
}

三、验证步骤

  1. 重启应用,确保没有Bean冲突异常。
  2. 发送符合条件的请求,查看控制台日志是否有Processing request with AuthorizationHeaderFilter的输出。
  3. 调试器断点现在应该能正常命中了。

内容的提问来源于stack exchange,提问作者isa_toltar

火山引擎 最新活动