IIWAB spring gateway中,Filter对责任链的使用,详解 - IIWAB

spring gateway中,Filter对责任链的使用,详解

IIWAB 昨天 ⋅ 18 阅读

在 Spring Cloud Gateway 中,过滤器(Filter) 是核心组件之一,其设计深度依赖于责任链模式。通过责任链,Gateway 能够将多个过滤器按特定顺序串联起来,对请求和响应进行逐层处理,实现路由转发、鉴权、日志记录、限流等功能。

一、责任链模式在 Spring Gateway 中的核心体现

Spring Gateway 的过滤器责任链遵循以下逻辑:

  1. 链的组成:由多个 GatewayFilter 实例组成,每个过滤器负责特定的处理逻辑(如修改请求头、校验 token、记录日志等)。
  2. 执行顺序:过滤器按预设顺序依次执行,每个过滤器处理完成后,将请求传递给下一个过滤器,直到完成全部处理并转发到目标服务,或在中途被拦截(如鉴权失败)。
  3. 双向处理:责任链分为**“前置处理”(请求发送到目标服务前)和“后置处理”**(目标服务返回响应后),类似 Servlet 中的 FilterChain,但更灵活。

二、核心组件与责任链实现

1. GatewayFilter:责任链的节点

GatewayFilter 是过滤器的核心接口,定义了处理请求的方法。其默认实现类 GatewayFilterAdapter 中,核心方法为:

 Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);
  • ServerWebExchange:封装了 HTTP 请求(ServerHttpRequest)和响应(ServerHttpResponse)的上下文对象。
  • GatewayFilterChain:代表过滤器链,用于将请求传递给下一个过滤器。

2. GatewayFilterChain:责任链的管理器

GatewayFilterChain 是责任链的核心接口,定义了如何将请求传递给下一个过滤器:

public interface GatewayFilterChain {
    Mono<Void> filter(ServerWebExchange exchange);
}

其默认实现类 DefaultGatewayFilterChain 维护了一个过滤器列表和当前执行索引,核心逻辑如下:

  • 保存所有待执行的 GatewayFilter 集合。
  • 记录当前执行到的过滤器索引(index)。
  • 执行当前过滤器后,通过 index+1 获取下一个过滤器,形成链式调用。

3. 责任链的构建与执行流程

Spring Gateway 会为每个路由(Route)构建独立的责任链,流程如下:

  1. 收集过滤器:当请求匹配到某个路由时,Gateway 会收集该路由关联的所有过滤器(包括全局过滤器 GlobalFilter 和路由专属过滤器 GatewayFilter)。
  2. 排序过滤器:通过 org.springframework.core.Ordered 接口的 getOrder() 方法对过滤器排序,确保执行顺序可控(值越小,优先级越高)。
  3. 构建责任链:将排序后的过滤器封装为 DefaultGatewayFilterChain,形成责任链。
  4. 执行责任链:从第一个过滤器开始执行,依次传递请求,直到所有过滤器完成处理,最终转发到目标服务。

三、过滤器执行的双向流程(重点)

Spring Gateway 的过滤器责任链是双向的,每个过滤器可以在“请求转发前”和“响应返回后”两个阶段处理逻辑,类似 AOP 的“环绕通知”。

执行流程示意图:

客户端请求 → [过滤器1 前置处理] → [过滤器2 前置处理] → ... → 转发到目标服务
                                                              ↓
客户端响应 ← [过滤器1 后置处理] ← [过滤器2 后置处理] ← ... ← 目标服务返回响应

代码示例(自定义过滤器):

@Component
public class CustomFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 1. 前置处理:请求转发到服务前执行(如打印日志、鉴权)
        System.out.println("前置处理:" + exchange.getRequest().getPath());

        // 2. 调用 chain.filter() 传递请求给下一个过滤器
        //    这是一个异步操作,返回的 Mono<Void> 会在后续流程(包括目标服务响应)完成后触发
        return chain.filter(exchange)
            .then(Mono.fromRunnable(() -> {
                // 3. 后置处理:服务返回响应后执行(如修改响应头、记录响应时间)
                System.out.println("后置处理:" + exchange.getResponse().getStatusCode());
            }));
    }

    @Override
    public int getOrder() {
        // 排序:值越小,越先执行
        return 0;
    }
}
  • 前置处理chain.filter(exchange) 之前的逻辑,用于处理请求(如校验 token、添加请求头)。
  • 后置处理chain.filter(exchange).then(...) 中的逻辑,用于处理响应(如记录响应时间、修改响应内容)。
  • 若前置处理中直接返回 Mono.error(...),则会中断责任链,不再向后传递(如鉴权失败时直接返回 401)。

四、全局过滤器与路由过滤器的融合

Spring Gateway 有两种过滤器:

  1. GlobalFilter:全局生效,对所有路由有效(如日志、限流过滤器)。
  2. GatewayFilter:仅对特定路由生效(如路由专属的重试过滤器)。

责任链构建时,会将这两种过滤器合并排序,统一纳入 DefaultGatewayFilterChain 执行。排序规则通过 getOrder() 实现,例如:

  • 内置的 Ordered.HIGHEST_PRECEDENCE(最高优先级)用于早期处理(如负载均衡)。
  • 内置的 Ordered.LOWEST_PRECEDENCE(最低优先级)用于后期处理(如响应日志)。

五、责任链模式的优势

  1. 解耦:请求发送者(客户端)与处理者(过滤器)分离,无需关心具体处理逻辑和顺序。
  2. 灵活性:新增或移除过滤器无需修改现有代码,只需实现 GlobalFilter 或配置路由过滤器即可。
  3. 可扩展性:通过排序机制,可精确控制过滤器执行顺序,满足复杂业务需求(如先鉴权后限流)。
  4. 双向处理:支持请求和响应的全链路干预,适合网关的流量管控场景。

六、总结

Spring Gateway 通过 GatewayFilterGatewayFilterChain 实现了责任链模式,核心特点是:

  • 过滤器按顺序组成责任链,依次处理请求和响应。
  • 支持前置/后置双向处理,灵活干预请求生命周期。
  • 全局过滤器与路由过滤器统一排序,共同参与责任链执行。

这种设计让 Gateway 能够轻松扩展各种功能(如鉴权、限流、日志),同时保持代码的清晰和解耦,是网关架构的核心设计思想之一。


全部评论: 0

    我有话说: