首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >【SpringCloud】Gateway Filter Factories && 过滤器执行顺序 && 自定义过滤器

【SpringCloud】Gateway Filter Factories && 过滤器执行顺序 && 自定义过滤器

原创
作者头像
lirendada
发布2026-02-20 21:03:17
发布2026-02-20 21:03:17
870
举报
文章被收录于专栏:JavaJava

一、Gateway Filter Factories(网关过滤器工厂)

Predicate 决定了请求由哪一个路由处理。如果在请求处理前后需要加一些逻辑,这就是 Filter(过滤器)的作用范围了。

  • Predicate:决定 "进不进这个路由"
  • Filter:决定 "进来后怎么处理"
代码语言:javascript
复制
Request
   ↓
RoutePredicate(匹配路由)
   ↓
GatewayFilter(改请求 / 鉴权 / 限流)
   ↓
转发到下游服务

Filter 分为两种类型:

  • Pre 类型过滤器:路由处理之前执行(请求转发到后端服务之前执行),在 Pre 类型过滤器中可以做鉴权、限流等。
  • Post 类型过滤器:请求执行完成后,将结果返回给客户端之前执行。

Spring Cloud Gateway 中内置了很多 Filter,用于拦截和链式处理web请求。比如权限校验、访问超时等设定。从作用范围上,Filter 可分为两种:

  • GatewayFilter:应用到单个路由或者一个分组的路由上。
  • GlobalFilter:应用到所有的路由上,即对所有的请求生效。

① GatewayFilter

GatewayFilter 与 Predicate 类似,都是在配置文件 application.yml 中配置,每个过滤器的逻辑都是固定的。

比如 AddRequestParameterGatewayFilterFactory 只需要在配置文件中写 AddRequestParameter,就可以为所有的请求添加一个参数,我们先通过一个例子来演示 GatewayFilter 如何使用。

快速上手

  1. application.yml 中添加 filter
    代码语言:javascript
    复制
    server:
      port: 10020  # 网关端口
    
    spring:
      application:
        name: gateway  # 应用名称
      cloud:
        nacos:
          discovery:
            server-addr: lirendada.art:8848  # Nacos地址
        gateway:
          routes:
            - id: order-service        
              uri: lb://order-service 
              predicates:              
                - Path=/order/**,/feign/**
              filters:
                - addRequestParameter=userName, lirendada  # 每个请求都带上键值对{userName, lirendada}
            - id: product-service
              uri: lb://product-service
              predicates:
                - Path=/product/**
                - After=2026-12-13T14:08:33.643172900+08:00[Asia/Shanghai]

该 filter 只添加在了 order-service 路由下,因此只对 order-service 路由生效。

2. 接收参数并打印:在 order-service 服务中接收请求的参数,并打印出来:

代码语言:javascript
复制
@Slf4j
@RestController
@RequestMapping("/feign")
public class FeginController {
    @Autowired
    private ProductApi productApi;

    @RequestMapping("/t1")
    public String test1(String userName) {
        log.info("接收到filter请求添加的参数:userName={}", userName);
        return productApi.p1(1);
    }
}

3. 测试:访问 http://127.0.0.1:8080/feign/t1 以及 http://127.0.0.1:10020/feign/t1 观察区别:

说明

Spring Cloud Gateway 提供了的 Filter 非常多,下面列出一些常见过滤器的说明。

详细可参考官方文档:GatewayFilterFactories

default-filters

前面提到的 filter 都是添加在指定路由下的,所以只对当前路由生效。若需要对全部路由生效,可以使用 spring.cloud.gateway.default-filters,这个属性需要一个 filter 的列表。

举个例子:

代码语言:javascript
复制
spring:
  application:
    name: gateway  # 应用名称
  cloud:
    nacos:
      discovery:
        server-addr: lirendada.art:8848  
    gateway:
      routes:
        - id: order-service        
          uri: lb://order-service  
          predicates:             
            - Path=/order/**,/feign/**
          filters:
            - AddRequestParameter=userName, lirendada
        - id: product-service
          uri: lb://product-service
          predicates:
            - Path=/product/**
            - After=2026-12-13T14:08:33.643172900+08:00[Asia/Shanghai]
      default-filters:  # 和routes是同级的
        - name: Retry
          args:
            retries: 3
            series: BAD_GATEWAY

然后修改一下之前 controller 的代码:

代码语言:javascript
复制
@RequestMapping("/t1")
public String test1(String userName, HttpServletResponse response) {
    log.info("接收到filter请求添加的参数:userName={}", userName);
    response.setStatus(502);
    return productApi.p1(1);
}

访问 http://127.0.0.1:10020/feign/t1 观察:

③ GlobalFilter

GlobalFilter 是 Spring Cloud Gateway 中的全局过滤器,它和 GatewayFilter 的作用是相同的,但和 default-filters 有以下区别:

维度

default-filters

GlobalFilter

配置方式

YAML

Java

生效范围

所有路由

所有路由

灵活性

极高

是否写代码

是否可访问业务资源

顺序控制

固定(内部)

可精确控制

可维护性

依赖实现质量

Spring Cloud Gateway 内置的全局过滤器也有很多,比如:

  • The Gateway Metrics Filter:网关指标,提供监控指标
  • Forward Routing Filter:用于本地 forword,请求不转发到下游服务器
  • ReactiveLoadBalancerClientFilter:针对下游服务,实现负载均衡
  • ……

更多过滤器参考:GlobalFilters

快速上手

  1. 添加依赖
    代码语言:javascript
    复制
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>

2. 添加配置

代码语言:javascript
复制
spring:
  cloud:
    gateway:
      metrics:
        enabled: true
management:
  endpoints:
    web:
      exposure:
        include: "*"
  endpoint:
    health:
      show-details: always
    shutdown:
      enabled: true

3.测试:访问 http://127.0.0.1:10020/actuator,显示所有监控的信息链接

二、过滤器执行顺序

一个项目中,既有 GatewayFilter,又有 GlobalFilter 时,执行的先后顺序是什么呢?

请求路由后,网关会把当前项目中的 GatewayFilterGlobalFilter 合并到一个过滤器链中,并进行排序,依次执行过滤器。

每一个过滤器都必须指定一个 int 类型的 order 值,默认值为 0,表示该过滤的优先级。order 值越小,优先级越高,执行顺序越靠前

  • Filter 通过实现 Order 接口或者添加 @Order 注解来指定 order 值。
  • Spring Cloud Gateway 提供的 Filter 由 Spring 指定,当然用户也可以自定义 Filter,由用户指定。
  • 当过滤器的 order 值一样时,会按照 defaultFilter > GatewayFilter > GlobalFilter 的顺序执行。

三、自定义过滤器

Spring Cloud Gateway 提供了过滤器的扩展功能,开发者可以根据实际业务来自定义过滤器,同样自定义过滤器也支持 GatewayFilterGlobalFilter 两种。

① 自定义GatewayFilter

自定义 GatewayFilter,需要去实现接口 GatewayFilterFactory,不过 SpringBoot 默认帮我们实现了一个抽象类 AbstractGatewayFilterFactory,所以直接继承该抽象类即可。

1. 创建 GatewayFilterFactory(核心)

代码语言:javascript
复制
@Slf4j
@Component
public class CustomGatewayFilterFactory extends AbstractGatewayFilterFactory<CustomGatewayFilterFactory.CustomConfig> implements Ordered {
    /**
     * 告诉 Gateway:这个 GatewayFilterFactory 使用哪一种配置对象,如何把 YAML 中的参数绑定进来。
     */
    public CustomGatewayFilterFactory() {
        super(CustomConfig.class);
    }

    @Override
    public GatewayFilter apply(CustomConfig config) {
        /**
         * Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain)
         *  ServerWebExchange: HTTP请求-响应交互的契约, 提供对HTTP请求和响应的访问, 服务器端请求属性, 请求实例,响应实例等, 类似Context角色
         *  GatewayFilterChain: 过滤器链
         *  Mono: Reactor核心类, 数据流发布者, Mono最多只触发一个事件, 所以可以把Mono 用于在异步任务完成时发出通知.
         *  Mono.fromRunnable: 创建一个包含Runnable元素的数据流
         */
        return new GatewayFilter() {
            @Override
            public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                log.info("[Pre] Custom Gateway Filter");  // 自定义的 GatewayFilter 逻辑
                return chain.filter(exchange).then(Mono.fromRunnable(() -> {
                    log.info("[Post] Custom Gateway Filter");
                }));
            }
        };
    }

    @Override
    public int getOrder() {
        return Ordered.LOWEST_PRECEDENCE; // 配置优先级, order越大, 优先级越低
    }

    @Data
    public static class CustomConfig {
        private String name;
    }
}
  1. 自定义过滤器的类名统一以 GatewayFilterFactory 结尾。因为默认情况下,过滤器的 name 会采用该定义类的前缀,这里的 name=Custom。
  2. apply() 方法中,可以同时包含 Pre 和 Post 过滤,并且 then() 方法是请求执行结束之后处理的。
  3. CustomConfig 是一个配置类,该类我们设定只有一个属性 name,会和 yml 的配置对应。
  4. 该类需要交给 Spring 管理,所以需要加五大注解。
  5. getOrder 表示该过滤器的优先级,值越大,优先级越低。

2. 配置过滤器

代码语言:javascript
复制
spring:
  application:
    name: gateway  
  cloud:
    nacos:
      discovery:
        server-addr: lirendada.art:8848  
    gateway:
      routes:
        - id: order-service        
          uri: lb://order-service  
          predicates:              
            - Path=/order/**,/feign/**
          filters:
            - AddRequestParameter=userName, lirendada
            - name: Custom
              args:
                name: lirendada  # 这里的 name 是 CustomConfig 的字段,要和上面区分开

3. 测试

重启服务,访问接口,观察日志:http://127.0.0.1:10020/order/1

② 自定义GlobalFilter

自定义 GlobalFilter 比较简单,它不需要额外的配置,因为它全局生效,所以只需要实现 GlobalFilter 接口,自动会过滤所有的 Filter。

1. 定义GlobalFilter

代码语言:javascript
复制
@Slf4j
@Component
public class CustomGlobalFilterFactory implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.info("[Pre] Custom GlobalFilter Filter");  // 自定义的 GlobalFilter 逻辑
        return chain.filter(exchange).then(Mono.fromRunnable(() -> {
            log.info("[Post] Custom GlobalFilter Filter");
        }));
    }

    @Override
    public int getOrder() {
        return Ordered.LOWEST_PRECEDENCE;
    }
}

2. 测

重启服务,访问接口,观察日志:http://127.0.0.1:10020/order/1

从日志中可以看出来,当 GatewayFilterGlobalFilter 过滤器的 order 值一样时,会先执行 GatewayFilter

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、Gateway Filter Factories(网关过滤器工厂)
    • ① GatewayFilter
      • 快速上手
      • 说明
      • default-filters
    • ③ GlobalFilter
      • 快速上手
  • 二、过滤器执行顺序
  • 三、自定义过滤器
    • ① 自定义GatewayFilter
      • 1. 创建 GatewayFilterFactory(核心)
      • 2. 配置过滤器
      • 3. 测试
    • ② 自定义GlobalFilter
      • 1. 定义GlobalFilter
      • 2. 测
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档