Gateway过滤器自定义实现某些需求

本文介绍了如何在Spring Cloud Gateway中自定义全局过滤器来统计API接口的响应时长,并展示了如何以类的形式书写过滤器以提高代码可读性。此外,还详细讲解了如何创建局部过滤器,限制特定IP访问服务,通过配置IPForbidGatewayFilterFactory实现客户端IP的黑白名单管理。通过这些自定义过滤器,可以更好地管理和优化服务的访问控制和性能监控。
摘要由CSDN通过智能技术生成

Gateway过滤器自定义实现某些需求

一、自定义全局过滤器-统计接口api响应时长
我们用一个常见的需求:api接口服务的响应时长的计算,这个需求的实现对请求访问链路的优化很有意义。具体实现看下文的代码及注释:

@Configuration
public class GlobalGatewayFilterConfig
{
@Bean
@Order(-100)
public GlobalFilter apiGlobalFilter()
{
return (exchange, chain) -> {
//获取请求处理之前的时间
Long startTime = System.currentTimeMillis();
//请求处理完成之后
return chain.filter(exchange).then().then(Mono.fromRunnable(() -> {
//获取请求处理之后的时间
Long endTime = System.currentTimeMillis();
//这里可以将结果进行持久化存储,我们暂时简单处理打印出来
System.out.println(
exchange.getRequest().getURI().getRawPath() +
", cost time : "
+ (endTime - startTime) + “ms”);
}));
};
}
}
@Order注解值越小,表示过滤器执行的优先级越高
我们使用《自定义PredicateFactory》那一节同样的测试用例,进行一下测试。zimug-server-gateway后台的打印结果如下:

通过上面的方法,可以在一个配置类里面写多个函数,每一个函数代表一个全局过滤器。

二、以class类的形式书写全局过滤器
上面的方法,当过滤器函数的实现内容比较复杂的时候,会导致单个类的代码行数过多,我们可以一个类写一个过滤器。

@Component
public class ApiGlobalFilter implements GlobalFilter, Ordered {

@Override
public int getOrder() {
    return -100;
}

@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    //获取请求处理之前的时间
    Long startTime = System.currentTimeMillis();
    //请求处理完成之后
    return chain.filter(exchange).then().then(Mono.fromRunnable(() -> {
        //获取请求处理之后的时间
        Long endTime = System.currentTimeMillis();
        //这里可以将结果进行持久化存储,我们暂时简单处理打印出来
        System.out.println(
            exchange.getRequest().getURI().getRawPath() + 
                    ", cost time : "
                    + (endTime - startTime) + "ms");
    }));
}

}
三、自定义局部过滤器-指定IP访问
在我们的系统中可能有几个功能是专门给系统管理员使用的,并不广泛开放。我们假设这样一个需求:只让某个ip(管理员操作的PC的IP)的客户端访问aservice-rbac权限管理服务,其他的ip不可以。

自定义Filter工厂需要继承 AbstractGatewayFilterFactory类,重写 apply 方法的逻辑。
在 apply 方法中可以通过 exchange.getRequest() 拿到 ServerHttpRequest 对象,从而可以获取到请求的参数、请求方式、请求头等信息。
在 apply 方法中可以通过chain操作过滤器链
@Component
@Order(99)
public class IPForbidGatewayFilterFactory
extends AbstractGatewayFilterFactory<IPForbidGatewayFilterFactory.Config> {

public IPForbidGatewayFilterFactory()
{
    super(Config.class);
}

@Override
public List<String> shortcutFieldOrder()
{
    return Arrays.asList("permitIp");  //对应config类的参数
}

@Override
public GatewayFilter apply(Config config)
{
    return (exchange, chain) -> {
        //获取服务访问的客户端ip
        String ip = exchange.getRequest().getRemoteAddress().getAddress().getHostAddress();
        if (config.getPermitIp().equals(ip)) {
            //如果客户端ip=permitIp,继续执行过滤器链允许继续访问
            return chain.filter(exchange);
        }
        //否则返回,拒绝请求
        exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
        return exchange.getResponse().setComplete();
    };
}

static public class Config
{
    private String permitIp;

    public String getPermitIp() {
        return permitIp;
    }

    public void setPermitIp(String permitIp) {
        this.permitIp = permitIp;
    }
}

}
类的命名需要以 GatewayFilterFactory结尾,比如 IPForbidGatewayFilterFactory,那么在配置文件中使用该Filter的时候 IPForbid就是这个Filter工厂的名称。
Config类可以定义一个或多个属性,要重写List shortcutFieldOrder()这个方法指定属性名称。
配置文件,因为只有一个参数,所以下图中的192.168.1.6将赋值给config类的唯一参数:permitIp

如果我们从不是192.168.1.6的这个客户端ip进行接口访问测试,将得到如下的结果:

如何为GatewayFilterFactory配置多个参数?
首先Config要有多个成员变量,如:permitIp、xxxx,其次配置文件进行如下配置

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值