Spring Cloud Gateway自定义Filter

今天我们来研究自定义Filter,自定义的Filter都是要实现GatewayFilter接口,如果需要指定排序则同时实现Order接口。filter有前置过滤器和后置过滤器,一般情况下,后置过滤器在then()方法里实现。下面实现一个自定义的filter,用来打印入参,以及统计请求到响应的耗时。

1.实现一个自定义过滤器

public class LogFilter implements GatewayFilter, Ordered {
	private static final String START_TIME = "startTime";
	@Override
	public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
		// 下面3行代码在前过滤器pre filter执行
		String url = exchange.getRequest().getURI().getRawPath();
		System.out.println("请求地址:" + url + ",入参:" + exchange.getRequest().getQueryParams().toString());
		exchange.getAttributes().put(START_TIME, System.currentTimeMillis());

		// chain.filter里面的逻辑相当于后过滤器post filter,会在NettyRoutingFilter之后执行
		return chain.filter(exchange).then(
				Mono.fromRunnable(() -> {
					Long startTime = exchange.getAttribute(START_TIME);
					if(startTime != null){
						System.out.println(url+ "耗时:" +
								(System.currentTimeMillis() - startTime) + "ms");
					}
				})
		);
	}

	@Override
	public int getOrder() {
		return 10;
	}
}

2.分析前置和后置过滤器的执行顺序

验证上面代码的后置处理逻辑
我们知道全局过滤器NettyRoutingFilter就是请求目标服务器的filter,所有的http和https都会由这个过滤器做路由的转发,我们可以在这个类中打印个日志证下后置处理逻辑的执行时机。
在这里插入图片描述
发送请求:curl http://localhost:8080/get
日志输出:

请求地址:/get,入参:{}
Routing netty.....
/get耗时:1089ms

以上就可以说明then()里面的代码就是后置处理逻辑。

过滤器的执行会被组装成一个类似责任链的方式顺序执行,这对于前置过滤器是比较好理解的,但是要理解后置过滤器就要明白Reactor的Mono执行原理。一个请求进来,SCG会把global filter和gateway filter组成一个列表,其结构如下,前置过滤器处理顺序跟这个列表一致,filter1->filter4
在这里插入图片描述

但是后置过滤经过类似责任链的方式被组织成了下面这个结构,其执行顺序就反过来了:
在这里插入图片描述
下面我们通过例子来解释这个处理逻辑,首先要mono1.then(mono2)代表的是,mono1执行完之后mono2才会执行。

	// 过滤器链
	private static Mono filterChain = Mono.empty();
	
	public static void main(String[] args) throws InterruptedException {
		for (int i =1; i < 6;i++){
			buildFilterChain(bulidFilter(i));
		}
		Flux.defer(() -> filterChain).subscribe();
		Thread.sleep(1000);
	}

	// 构建过滤器链
	private static Mono buildFilterChain(Mono mono){
		return filterChain = mono.then(filterChain);
	}
	
	// 模拟创建filter
	private static Mono bulidFilter(int order){
		System.out.println("第" + order + "个过滤器的前置逻辑执行");
		return Mono.fromRunnable(() -> System.out.println("第" + order + "个过滤器的后置逻辑执行"));
	}

结果输出如下

第1个过滤器的前置逻辑执行
第2个过滤器的前置逻辑执行
第3个过滤器的前置逻辑执行
第4个过滤器的前置逻辑执行
第5个过滤器的前置逻辑执行
第5个过滤器的后置逻辑执行
第4个过滤器的后置逻辑执行
第3个过滤器的后置逻辑执行
第2个过滤器的后置逻辑执行
第1个过滤器的后置逻辑执行

3.小结

本篇文章从自定义一个过滤器出发,了解前置和后置过滤器的执行时机,然后分析了前置和后置过滤逻辑的实现原理,最后给出一个示例加深对这个原理的理解。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值