Spring Cloud Gateway 核心篇:深入解析过滤器(Filter)机制与实战

**摘要:**​ 本文将带你深入 Spring Cloud Gateway 的核心组件------过滤器(Filter)。我们将从基础配置讲起,涵盖默认过滤器(Default Filters)、全局过滤器(Global Filters)以及如何自定义一个强大的过滤器工厂(Custom Filter Factory)。通过图文结合与代码实战,助你彻底掌握 Gateway 的流量处理能力。

1. 过滤器(Filter)是什么?

在 Spring Cloud Gateway 中,过滤器是处理请求和响应的核心组件。它们在请求到达目标服务之前(Pre)或响应返回客户端之前(Post)执行逻辑,用于修改请求头、响应头、重写路径、限流、鉴权等操作。

请求经过一系列过滤器链(Filter Chain)后到达目的地,响应再逆向经过过滤器链返回:

2. 基础配置:路由过滤器(Route Filters)

这是最常用的过滤器,绑定在具体的路由规则上。

2.1 内置过滤器示例

在配置中,使用了 RewritePath过滤器来重写请求路径:

复制代码
routes:
  - id: product-route
    uri: lb://service-product
    predicates:
      - Path=/api/product/**
    filters:
      # 将 /api/product/xxx 重写为 /xxx
      - RewritePath=/api/product/(?<segment>.*),/$\{segment}

2.2 默认过滤器(Default Filters)

默认过滤器会应用到所有路由上,无需在每个路由中重复配置。

复制代码
spring:
  cloud:
    gateway:
      default-filters:
        # 为所有响应添加 X-Response 头
        - AddResponseHeader=X-Response, 123

3. 全局过滤器(Global Filters)

全局过滤器作用于所有路由,通常用于日志记录、统一鉴权等跨切面逻辑。

3.1 实战:请求耗时监控

RtGlobalFilter是一个典型的全局过滤器,用于记录请求的开始和结束时间:

java 复制代码
@Component
@Slf4j
public class RtGlobalFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        String path = request.getURI().toString();
        log.info("进入全局过滤器: {} 开始时间: {}", path, System.currentTimeMillis());

        // doFinally 会在请求处理完成后执行,无论成功或失败
        return chain.filter(exchange).doFinally(result -> {
            log.info("全局过滤器结束: {} 结束时间: {}", path, System.currentTimeMillis());
        });
    }

    @Override
    public int getOrder() {
        return 0; // 优先级,数值越小优先级越高
    }
}

4. 高阶玩法:自定义过滤器工厂(Custom Filter Factory)

当内置过滤器无法满足需求时,我们可以自定义过滤器。 OnceTokenGatewayFilterFactory是一个非常实用的例子,它允许动态生成 UUID 或 JWT。

4.1 核心代码解析

这个工厂继承自 AbstractNameValueGatewayFilterFactory,这意味着它接受"名称"和"值"两个参数。

java 复制代码
@Component
public class OnceTokenGatewayFilterFactory extends AbstractNameValueGatewayFilterFactory {
    @Override
    public GatewayFilter apply(NameValueConfig config) {
        return (exchange, chain) -> {
            // 注意:这里是 chain.filter(exchange).then(...)
            // 表示先放行请求,等响应回来后再执行后续逻辑(Post Filter)
            return chain.filter(exchange).then(Mono.fromRunnable(() -> {
                ServerHttpResponse response = exchange.getResponse();
                HttpHeaders headers = response.getHeaders();
                String value = config.getValue();

                // 动态逻辑:如果值是 uuid,则生成 UUID
                if ("uuid".equalsIgnoreCase(value)) {
                    value = UUID.randomUUID().toString();
                }
                // 动态逻辑:如果值是 jwt,则返回预设的 JWT
                if ("jwt".equalsIgnoreCase(value)) {
                    value = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...";
                }
                
                // 添加响应头
                headers.add(config.getName(), value);
            }));
        };
    }
}

4.2 配置使用

在 YAML 中配置该自定义过滤器:

复制代码
routes:
  - id: product-route
    uri: lb://service-product
    filters:
      - RewritePath=/api/product/(?<segment>.*),/$\{segment}
      # 使用自定义过滤器,添加 X-Response-Token 头,值为 uuid
      - OnceToken=X-Response-Token,uuid

5. 总结与建议

  1. Pre vs Post: ​ 注意 chain.filter(exchange)的位置。如果逻辑写在 then之前,是 Pre Filter(前置);写在 then之后,是 Post Filter(后置)。 OnceToken是典型的后置过滤器,用于修改响应。

  2. Order 优先级: ​ 全局过滤器的 getOrder()方法决定了执行顺序,合理设置可以避免逻辑冲突。

  3. **扩展性:**​ 自定义过滤器工厂是 Gateway 最强大的特性之一,可以封装复杂的业务逻辑(如签名、加密、限流),让配置层保持简洁。

相关推荐
ss2734 小时前
食谱推荐系统功能测试如何写?
java·数据库·spring boot·功能测试
Smart-佀4 小时前
涨薪秘技:智能家居中的BLE协议与实现
网络·arm开发·嵌入式硬件·microsoft
2301_811274314 小时前
基于SpringBoot的智能家居管理系统
spring boot·后端·智能家居
南京码讯光电技术有限公司4 小时前
工业级CPE,4G/5G+WiFi融合,破解严苛环境无线覆盖难题
网络·5g
AI人工智能+电脑小能手4 小时前
【大白话说Java面试题】【Java基础篇】第15题:JDK1.7中HashMap扩容为什么会发生死循环?如何解决
java·开发语言·数据结构·后端·面试·哈希算法
舒一笑4 小时前
我把设备指纹生成逻辑拆开了:它到底凭什么区分不同设备?
后端·程序员·掘金技术征文
倔强的石头1064 小时前
【Linux指南】基础IO系列(八):实战衔接 —— 给微型 Shell 添加完整重定向功能
linux·运维·服务器
try2find4 小时前
打印ascii码报错问题
java·linux·前端
014-code4 小时前
CompletableFuture 实战模板(超时、组合、异常链处理)
java·数据库
Nicander4 小时前
多数据源下@transcation事务踩坑
java·后端