本文基于 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. 在论坛中出现的比较难的sql问题:21(递归问题 检索某个节点下所有叶子节点)

    原文:在论坛中出现的比较难的sql问题:21(递归问题 检索某个节点下所有叶子节点) 最近,在论坛中,遇到了不少比较难的sql问题,虽然自己都能解决,但发现过几天后,就记不起来了,也忘记解决的方法了. ...

  2. 高德地图模糊搜索地址(elementUI)

    首先引入AMap: 1.在index.html引入AMap <script type="text/javascript" src="http://webapi.am ...

  3. nginx的access_log与error_log

     参考文章:https://juejin.im/post/5aa09bb3f265da238f121b6c 本篇文章主要介绍一下 nginx 服务器两种日志查看:access_log.error_lo ...

  4. 【小知识点】js无需刷新在url地址添加参数

    今天后端同事找我,问我一个关于js无需刷新在url地址添加参数的方法. 然后我百度啊,终于在一篇文章找到了办法,非常简单的一句代码. window.history.pushState({}, 0, w ...

  5. Android NDK 学习之接受Java传入Object数组

    本博客主要是在Ubuntu 下开发,且默认你已经安装了Eclipse,Android SDK, Android NDK, CDT插件. 在Eclipse中添加配置NDK,路径如下Eclipse-> ...

  6. java的输入流中的两个坑

    1.输入流的所有实例中的read()方法皆是阻塞的. 输入流只会在发生错误或者异常关闭的时候回返回-1,如果流中没有数据,不会返回-1而是一直阻塞. 2.BufferedReader的readLine ...

  7. 孤陋寡闻了吧?Python 居然可以做这30件神奇好玩的事情(附教程)

    知乎上有个浏览超过400万的问题:可以用 Python 编程语言做哪些神奇好玩的事情? 我先举一个很不专业的栗子...... 然后再找几个人抬一堆例子来...... 不是很稀饭<复联>嘛, ...

  8. Linux安装java环境和maven

    安装OpenJDK软件包: apt-get install openjdk-8-jdk 查看版本信息java -version 则代表安装成功 安装maven可以使用自己本机下载好的mavan使用Xf ...

  9. C语言二级指针底层实现

    C语言中,Pointers to Pointers,即二级指针. 一级指针和二级指针的值都是指向一个内存单元: 一级指针指向的内存单元存放的是源变量的值, 二级指针指向的内存单元存放的是一级指针的地址 ...

  10. Shell脚本字符串匹配及日常命令工具 - 用法总结(技巧指南)

    Shell提供了很多字符串和文件处理的命令,如awk.expr.grep.sed等命令,还有文件的排序.合并和分割等一系列的操作命令.下面重点总结下Shell字符串处理.文本处理以及各类命令及函数用法 ...