(一)GlobalFilter

GlobalFilter和GatewayFilter的作用是相同的,只是GlobalFilter针对所有的路由配置生效。Spring Cloud Gateway内置的全局过滤器也有很多,比如∶
1:GatewayMetricsFilter,提供监控指标。
2:LoadBalancerClientFilter,整合Ribbon针对下游服务实现负载均衡。
3:ForwardRoutingFilter,用于本地forward,请求不转发到下游服务器。
4:NettyRoutingFilter,使用Netty的HttpClient转发HTTP、HTTPS请求。

全局过滤链的执行顺序是,当Gateway接收到请求时,Filtering Web Handler处理器会将所有的GlobalFilter实例及所有路由上所配置的GatewayFilter实例添加到一条过滤器链中。该过滤器链里的所有过滤器都会按照@Order注解所指定的数字大小进行排序。

(二)自定义过滤器

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

(三)自定义Gateway Filter

首先创建一个自定义过滤器类GpDefineGatewayFilterFactory,继承AbstractGatewayFilterFactory。

@Service
@Slf4j
public class GpDefineGatewayFilterFactory extends AbstractGatewayFilterFactory<GpDefineGatewayFilterFactory.GpConfig>{

    public GpDefineGatewayFilterFactory(){
        super(GpConfig.class);
    }

    @Override
    public GatewayFilter apply(GpConfig config ) {
        return ((exchange, chain) -> {
            ServerHttpRequest request = exchange.getRequest();
            log.info("前置局部过滤器,name:"+config.getName());
            return chain.filter(exchange).then(Mono.fromRunnable(()->{
                log.info("后置局部过滤器");
            }));
        });
    }

    public static class GpConfig{
        private String name;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }
}

在上述代码中,有几点需要注意。
1:类名必须要统一以GatewayFilterFactory结尾,因为默认情况下过滤器的name会采用该自定义类的前缀。这里的name=GpDefine。
2:在apply方法中,同时包含Pre和Post过滤。在then方法中是请求执行结束之后的后置处理。
3:GpConfig是一个配置类,该类中只有一个属性name。这个属性可以在yml文件中使用。
4:该类需要装载到Spring IoC容器,此处使用@Service注解实现。

接下来,在application.yml文件中配置该自定义过滤器。
在这里插入图片描述

spring:
  cloud:
    gateway:
      routes:
        - id: define_filter
          predicates:
            - Path=/gateway/**
          filters:
            - name: GpDefine
              args:
                name: Gp_Mic
            - name: RequestRateLimiter
              args:
                denyEmptyKey: false
                emptyKeyStatus: SERVICE_UNAVAILABLE
                keyResolver: '#{@ipAddressKeyResolver}'
                redis-rate-limiter.replenishRate: 1
                redis-rate-limiter.burstCapacity: 2
            - StripPrefix=1
          uri: http://localhost:8081/say

其中,name属性就是GpDefineGatewayFilterFactory的前缀。而args中的name属性是GpConfig配置类中声明的属性,这个属性配置好之后,可以在代码中获得这个name对应的值Gp_Mic

【提示】
对于请求中的Request和Response以及过滤器链可以通过如下对象获取
在这里插入图片描述

(四)自定义GlobalFilter

GlobalFilter的实现和JavaEE的方式类似,它不需要额外的配置,只需要实现GlobalFilter接口,自动会过滤所有的Route.

@Service
@Slf4j
public class GpDefineFilter implements GlobalFilter,Ordered{
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.info("前置全局过滤器");
        return chain.filter(exchange).then(Mono.fromRunnable(()->{
            log.info("后置全局过滤器");
        }));
    }
    @Override
    public int getOrder() {
        return 0;
    }
}

getOrder表示该过滤器的执行顺序,值越小,执行优先级越高。
需要注意的是,我们通过AbstractGatewayFilterFactory实现的局部过滤器没有指定order,它的默认值是0,如果想要设置多个过滤器的执行顺序,可以重写getOrder方法。

【测试,运行程序并结合上面全局过滤器和局部过滤器】
在这里插入图片描述
在这里插入图片描述

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐