本文基于 spring cloud gateway 2.0.1

1、简介

GatewayFilter 网关过滤器用于拦截并链式处理web请求,可以实现横切的与应用无关的需求,比如:安全、访问超时的设置等。

从类图中可以看到,GatewayFilter 有三个实现类:

  • OrderedGatewayFilter 是一个有序的网关过滤器

  • GatewayFilterAdapter 是一个适配器类,是web处理器(FilteringWebHandler)中的内部类

  • ModifyResponseGatewayFilter 是一个内部类,用于修改响应体

本文就分别介绍一下网关过滤器的实现类。

2、有序的网关过滤器 OrderedGatewayFilter

过滤器大多都是有优先级的,因此有序的网关过滤器的使用场景会很多。在实现过滤器接口的同时,有序网关过滤器也实现了 Ordered 接口,构造函数中传入需要代理的网关过滤器以及优先级就可以构造一个有序的网关过滤器。具体的过滤功能的实现在被代理的过滤器中实现的,因此在此只需要调用代理的过滤器即可。

public class OrderedGatewayFilter implements GatewayFilter, Ordered {

	private final GatewayFilter delegate;
private final int order; public OrderedGatewayFilter(GatewayFilter delegate, int order) {
this.delegate = delegate;
this.order = order;
}
--------------------------------省略-------------------------------
}

3、网关过滤器适配器 GatewayFilterAdapter

在网关过滤器链 GatewayFilterChain 中会使用 GatewayFilter 过滤请求,GatewayFilterAdapter的作用就是将全局过滤器 GlobalFilter 适配成 网关过滤器 GatewayFilter。

// FilteringWebHandler.java

private static class GatewayFilterAdapter implements GatewayFilter {

		private final GlobalFilter delegate;

		public GatewayFilterAdapter(GlobalFilter delegate) {
this.delegate = delegate;
} @Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
return this.delegate.filter(exchange, chain);
} @Override
public String toString() {
final StringBuilder sb = new StringBuilder("GatewayFilterAdapter{");
sb.append("delegate=").append(delegate);
sb.append('}');
return sb.toString();
}
}

4、ModifyResponseGatewayFilter

ModifyResponseGatewayFilter 是 ModifyResponseBodyGatewayFilterFactory 的内部类,用于修改响应体的信息

// ModifyResponseBodyGatewayFilterFactory.java

	public class ModifyResponseGatewayFilter implements GatewayFilter, Ordered {
private final Config config; public ModifyResponseGatewayFilter(Config config) {
this.config = config;
} @Override
@SuppressWarnings("unchecked")
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { ServerHttpResponseDecorator responseDecorator = new ServerHttpResponseDecorator(exchange.getResponse()) { @Override
public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) { Class inClass = config.getInClass();
Class outClass = config.getOutClass(); String originalResponseContentType = exchange.getAttribute(ORIGINAL_RESPONSE_CONTENT_TYPE_ATTR);
HttpHeaders httpHeaders = new HttpHeaders();
//explicitly add it in this way instead of 'httpHeaders.setContentType(originalResponseContentType)'
//this will prevent exception in case of using non-standard media types like "Content-Type: image"
httpHeaders.add(HttpHeaders.CONTENT_TYPE, originalResponseContentType);
ResponseAdapter responseAdapter = new ResponseAdapter(body, httpHeaders);
DefaultClientResponse clientResponse = new DefaultClientResponse(responseAdapter, ExchangeStrategies.withDefaults()); //TODO: flux or mono
Mono modifiedBody = clientResponse.bodyToMono(inClass)
.flatMap(originalBody -> config.rewriteFunction.apply(exchange, originalBody)); BodyInserter bodyInserter = BodyInserters.fromPublisher(modifiedBody, outClass);
CachedBodyOutputMessage outputMessage = new CachedBodyOutputMessage(exchange, exchange.getResponse().getHeaders());
return bodyInserter.insert(outputMessage, new BodyInserterContext())
.then(Mono.defer(() -> {
long contentLength1 = getDelegate().getHeaders().getContentLength();
Flux<DataBuffer> messageBody = outputMessage.getBody();
//TODO: if (inputStream instanceof Mono) {
HttpHeaders headers = getDelegate().getHeaders();
if (/*headers.getContentLength() < 0 &&*/ !headers.containsKey(HttpHeaders.TRANSFER_ENCODING)) {
messageBody = messageBody.doOnNext(data -> headers.setContentLength(data.readableByteCount()));
}
// }
//TODO: use isStreamingMediaType?
return getDelegate().writeWith(messageBody);
}));
} @Override
public Mono<Void> writeAndFlushWith(Publisher<? extends Publisher<? extends DataBuffer>> body) {
return writeWith(Flux.from(body)
.flatMapSequential(p -> p));
}
}; return chain.filter(exchange.mutate().response(responseDecorator).build());
} @Override
public int getOrder() {
return NettyWriteResponseFilter.WRITE_RESPONSE_FILTER_ORDER - 1;
} }

Spring Cloud Gateway(九):网关过滤器 GatewayFilter的更多相关文章

  1. Spring Cloud gateway 三 自定义过滤器GatewayFilter

    之前zuul 网关介绍.他有过滤器周期是四种,也是四种类型的过滤器.而gateway 只有俩种过滤器:"pre" 和 "post". PRE: 这种过滤器在请求 ...

  2. Spring Cloud Gateway 服务网关快速上手

    Spring Cloud Gateway 服务网关 API 主流网关有NGINX.ZUUL.Spring Cloud Gateway.Linkerd等:Spring Cloud Gateway构建于 ...

  3. Spring Cloud Gateway服务网关

    原文:https://www.cnblogs.com/ityouknow/p/10141740.html Spring 官方最终还是按捺不住推出了自己的网关组件:Spring Cloud Gatewa ...

  4. Spring Cloud (14) 服务网关-过滤器

    Spring Cloud Zuul作为网关所具备的最基本的功能:路由,还具备另外一个核心的功能:过滤器. 过滤器 通过Spring Cloud Zuul实现的路由功能,我们的微服务可以通过统一的API ...

  5. Spring Cloud Alibaba学习笔记(21) - Spring Cloud Gateway 自定义全局过滤器

    在前文中,我们介绍了Spring Cloud Gateway内置了一系列的全局过滤器,本文介绍如何自定义全局过滤器. 自定义全局过滤需要实现GlobalFilter 接口,该接口和 GatewayFi ...

  6. Spring Cloud Gateway之全局过滤器在工作中的使用场景

    一.使用注意事项 1.全局过滤器作用于所有的路由,不需要单独配置. 2.通过@Order来指定执行的顺序,数字越小,优先级越高. 二.默认全局拦截器的整体架构 三.实战场景,例如,校验token.记录 ...

  7. Spring Cloud gateway 网关四 动态路由

    微服务当前这么火爆的程度,如果不能学会一种微服务框架技术.怎么能升职加薪,增加简历的筹码?spring cloud 和 Dubbo 需要单独学习.说没有时间?没有精力?要学俩个框架?而Spring C ...

  8. Spring Cloud gateway 五 Sentinel整合

    微服务当前这么火爆的程度,如果不能学会一种微服务框架技术.怎么能升职加薪,增加简历的筹码?spring cloud 和 Dubbo 需要单独学习.说没有时间?没有精力?要学俩个框架?而Spring C ...

  9. Spring Cloud gateway 六 Sentinel nacos存储动态刷新

    微服务当前这么火爆的程度,如果不能学会一种微服务框架技术.怎么能升职加薪,增加简历的筹码?spring cloud 和 Dubbo 需要单独学习.说没有时间?没有精力?要学俩个框架?而Spring C ...

  10. Spring Cloud Gateway GatewayFilter的使用

    Spring Cloud Gateway GatewayFilter的使用 一.GatewayFilter的作用 二.Spring Cloud Gateway内置的 GatewayFilter 1.A ...

随机推荐

  1. Extending WCF using IServiceBehavior, IOperationBehavior, and IParameterInspector

    [ServiceContract(Name = "PasswordGenerator")] public interface IPasswordGenerator { [Opera ...

  2. kvm第五章--虚拟迁移

  3. vue 做的tabBar组件

    效果如下 调用 <tabbar :selected='selected'></tabbar> 组件 <template> <div class='tabbar ...

  4. mysql数据库事件

    今天在测试一个存储过程和数据库事件,就是到某一个固定时间,数据库自动调用一个存储过程实现一些功能. 单独来看事件是没有问题的 MINUTE STARTS '2015-12-09 02:00:00' O ...

  5. Git 日常命令

    克隆项目:git clone addr dir   切换分支,分支并没有 git checkout -b production origin/production 分支已存在,单纯切换分支 git c ...

  6. JAVA笔记整理(四),JAVA中的封装

    什么是封装 所谓的封装就是把数据项和方法作为一个独立的整体隐藏在对象的内部,具体的实施细节不对外提现,仅仅保留有限的外部接口,封装外的用户只能通过接口来进行操作.就好比开启一台电脑需要进行很多个步骤, ...

  7. java - day019 - 数据库

    https://www.cnblogs.com/myxq666/p/7787744.html Mac 安装MySQL步骤 什么是数据库 数据库: 英文名称Database ,简称 DB 数据库是按照数 ...

  8. nginx实现fastcgi反向代理

    实现FastCGI: CGI的由来:最早的Web服务器只能简单地响应浏览器发来的HTTP请求,并将存储在服务器上的HTML文件返回给浏览器,也就是静态html文件,但是后期随着网站功能增多网站开发也越 ...

  9. hexo Yelee 主题的busuanzi网站统计没数字显示问题解决

    j进入你的Yelee主题路径: themes\yelee\source\css\_partial 修改该路径下的: footer.styl 修改文件内容: 将内容改为: 然后你的站点就可以了

  10. Ubuntu16.04, CUDA8 CUDNN6 下安装 Tensorflow-gpu, Keras, Pytorch, fastai

    如何访问tensorflow官方网站 tensorflow官方网站变为:https://tensorflow.google.cn/ 安装深度学习框架 0. ubuntu查看CUDA和cuDNN版本 C ...