本文基于 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. 遗传算法python实现

    最近看了一下遗传算法,使用轮盘赌选择染色体,使用单点交叉,下面是代码实现(python3) import numpy as np import random from scipy.optimize i ...

  2. 依赖: libcheese-gtk23 (>= 3.4.0)

    unity-control-center : 依赖: libcheese-gtk23 (>= 3.4.0) 但是它将不会被安装                         依赖: libch ...

  3. 基于re模块的计算器

    最终计算器需求: 实现加减乘除及拓号优先级解析 用户输入 1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - ...

  4. Django_rest_framework分页

    分页基本流程及配置 1.基于LimitOffsetPagination做分页,根据配置 from rest_framework.pagination import LimitOffsetPaginat ...

  5. 【转载】 Asp.Net MVC网站提交富文本HTML标签内容抛出异常

    今天开发一个ASP.NET MVC网站时,有个页面使用到了FCKEditor富文本编辑器,通过Post方式提交内容时候抛出异常,仔细分析后得出应该是服务器阻止了带有HTML标签内容的提交操作,ASP. ...

  6. Modelsim问题集锦

    前言 收集工程调试中遇到的modelsim问题. 问题 (1)仿真发现时钟信号和理论上的数据信号没有边沿对齐. 解决:一般是时钟精度不匹配的问题. 如果想要1ns的精度则代码中的精度需设置为: v语法 ...

  7. 【已解决】老型号电脑需要按F1键才能进入系统

    [已解决]老型号电脑需要按F1键才能进入系统 本文作者:天析 作者邮箱:2200475850@qq.com 发布时间: Tue, 16 Jul 2019 20:49:00 +0800 问题描述:电脑因 ...

  8. 阿里云服务器(Ubuntu16.04 64位)的使用

    购买阿里云服务器 1.打开阿里云官方网站,账号登录,选择产品中的云服务器 ECS 2.根据自身需求,选择合适的阿里云服务器系统,(1)点击一键购买,(2)选择地域,(3)根据自身需求,选择系统,这里选 ...

  9. laravel登录后其他页面拿不到登录信息

    登录本来是用表单的,我自作聪明的使用ajax提交 public function login(Request $request){ $data = $request->input(); $dat ...

  10. android开机启动流程说明

    android开机启动流程说明 第一步:启动linux 1.Bootloader 2.Kernel 第二步android系统启动:入口为init.rc(system\core\rootdir) 1./ ...