Gateway自定义过滤器——全局过滤器
一、什么是全局过滤器🍉
首先,我们要知道全局过滤器其实是特殊路由过滤器(特殊的GatewayFilter),会有条件地作用于所有路由。
为什么要自定义全局过滤器?就好比是看大门的保安大叔,平时主要是做好进出大门外来人员登记即可,但是因为新冠疫情,现在还需要给外来人员测量体温等等。而已有的全局过滤器就好比是登记操作,而自定义的全局过滤器就好比是测量体温操作,是结合具体场景添加的。
比如以下场景:
-
认证判断
-
权限校验
-
黑白名单
-
跨域配置
工作原理:
当请求与路由匹配时,过滤WebHandler会将GlobalFilter的所有实例和GatewayFilter的所有特定于路由的实例添加到过滤器链中。该组合的过滤器链由org.springframework.core.Ordered接口排序,您可以通过实现getOrder()方法进行设置。
由于Spring Cloud Gateway区分了过滤器逻辑执行的“前”阶段和“后”阶段,因此具有最高优先级的过滤器在“前”阶段中是第一个,在“后”阶段中是最后一个。
二、自带的全局过滤器包含哪些🍉
要自定义全局过滤,首先我们应该去了解一下gateway自带的主要的全局过滤器有哪些,并了解他们的作用。
- ForwardRoutingFilter
ForwardRoutingFilter在exchange属性ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR中查找URI。如果URL具有转发scheme(例如forward:/// localendpoint),则它将使用Spring DispatcherHandler来处理请求。请求URL的路径部分被转发URL中的路径覆盖。未经修改的原始URL会附加到ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR属性中的列表中。
- LoadBalancerClientFilter
LoadBalancerClientFilter在ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR的exchange属性中查找URI。如果URL的方案为lb(例如lb:// myservice),它将使用Spring Cloud LoadBalancerClient将名称(在本例中为myservice)解析为实际的主机和端口,并替换同一属性中的URI。未经修改的原始URL会附加到ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR属性中的列表中。过滤器还会在ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR属性中查找其是否等于lb。如果是,则适用相同的规则。下面的清单配置一个LoadBalancerClientFilter:
spring:cloud:gateway:routes:- id: myRouteuri: lb://servicepredicates:- Path=/service/**
注意1:默认情况下,当在LoadBalancer中找不到服务实例时,将返回503。您可以通过设置spring.cloud.gateway.loadbalancer.use404 = true将网关配置为返回404。
注意2:从LoadBalancer返回的ServiceInstance的isSecure值将覆盖对网关的请求中指定的方案。例如,如果请求通过HTTPS进入网关,但是ServiceInstance指示它不安全,则下游请求通过HTTP发出。相反的情况也可以适用。但是,如果在网关配置中为路由指定了GATEWAY_SCHEME_PREFIX_ATTR,则会删除前缀,并且路由URL产生的方案将覆盖ServiceInstance配置。
注意3:LoadBalancerClientFilter在默认情况下使用阻塞的LoadBalancerClient。建议改用ReactiveLoadBalancerClientFilter。可以通过将spring.cloud.loadbalancer.ribbon.enabled的值设置为false来切换到该值。
- ReactiveLoadBalancerClientFilter
ReactiveLoadBalancerClientFilter与上面的LoadBalancerClientFilter类似,差异主要是ReactiveLoadBalancerClientFilter是非阻塞的。
注意1:与LoadBalancerClientFilter一样,默认情况下,当ReactorLoadBalancer无法找到服务实例时,将返回503。您可以通过设置spring.cloud.gateway.loadbalancer.use404 = true将网关配置为返回404。
- NettyRoutingFilter
如果ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR的exchange属性中的URL带有http或https,则将运行NettyRoutingFilter。它使用Netty HttpClient发出下游代理请求。响应将放入ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR的exchange属性中,供后面的过滤器使用。 (还有一个实验性的WebClientHttpRoutingFilter,它执行相同的功能,但不需要Netty。)
经过该过滤器时,会通过ServerWebExchangeUtils.setAlreadyRouted方法把exchange对象标记为“已路由”。
- RouteToRequestUrlFilter
如果ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR的exchange属性中存在Route对象,则RouteToRequestUrlFilter将运行。它基于请求URI创建一个新URI,但使用Route对象的URI属性进行更新。新的URI放置在ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR的exchange属性中。
如果URI具有scheme前缀(例如lb:ws://serviceid),则将从URI中剥离lb方案,并将其放在ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR中,以供后面在过滤器链中使用。
- WebsocketRoutingFilter
顾名思义,WebsocketRoutingFilter过滤器是用于处理websocket请求的,如果ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR的exchange属性中的URL具有ws或wss的schema,则将运行WebsocketRoutingFilter。它使用Spring WebSocket基础结构向下游转发websocket请求。
您可以通过为URI加上lb前缀来平衡websocket的负载,例如lb:ws://serviceid
经过该过滤器时,会通过ServerWebExchangeUtils.setAlreadyRouted方法把exchange对象标记为“已路由”。
配置示例如下,通常情况下,除了配置ws,还需要配置一个http的,因为发起websocket连接的请求是http请求。
# 官方示例
spring:cloud:gateway:routes:# SockJS route- id: websocket_sockjs_routeuri: http://localhost:3001predicates:- Path=/websocket/info/**# Normal Websocket route- id: websocket_routeuri: ws://localhost:3001predicates:- Path=/websocket/**
- GatewayMetricsFilter
该过滤器主要用于做网关度量监控的,要启用,需添加spring-boot-starter-actuator依赖。然后,默认情况下,只要属性spring.cloud.gateway.metrics.enabled未设置为false,GatewayMetricsFilter就会运行。此过滤器添加一个带有以下标记的计时器度量标准,名为gateway.requests:
- routeId: 路由ID.
- routeUri: 需要路由的API
- outcome: 结果分类参考 HttpStatus.Series.
- status: 返回给客户端的http status
- httpStatusCode: 返回给客户端的http status
- httpMethod: 用户请求的http Method
这些指标随后可从/actuator/metrics/gateway.requests中进行抓取,并可轻松地与Prometheus集成以创建Grafana dashboard。
要启用prometheus端点,请添加micrometer-registry-prometheus依赖。
三、如何自定义全局过滤器🍉
在这里演示过滤黑白名单
1.在配置文件中定义黑白名单🥝

#配置端口号
server:port: 81
#服务名称
spring:application:name: qy165-lzq
#配置路径规则cloud:gateway:routes:- id: lzq01 #路由的唯一标识-------随便起只要不重复就可以 如果不写默认uuid创建uri: http://localhost:8001 # 真是转发地址predicates: # 断言 当满足当前条件时进行跳转到uri 可以理解为判断- Path=/aaa/**- id: lzq02uri: lb://lzq-01 #lb 表示跳转方式 获取nacos上的服务器名predicates:- Path=/aaa/**
#连接nacos地址nacos:discovery:server-addr: localhost:8848register-enabled: falsefilter:whitePaths:- "/product/login"- "/product/aaa"- "/product/bbb"blackPaths:- "/product/ccc"
2.定义工具类读取黑白名单🥝

package com.lzq.filter;import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;import java.util.HashSet;
import java.util.Set;@Component
@ConfigurationProperties(prefix = "filter")
@Data
public class FilterUrl {private Set<String> whitePaths=new HashSet<>();private Set<String> blackPaths=new HashSet<>();}
3.编写过滤器🥝
定义实体类实现接口

package com.lzq.filter;import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
@Component
public class LogFilter implements GlobalFilter, Ordered {@Autowiredprivate FilterUrl filterUrl;@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {ServerHttpRequest request = exchange.getRequest();ServerHttpResponse response = exchange.getResponse();//过滤的业务代码//1.获取请求路径---String path = request.getPath().toString();//判断该路径是否放行路径if(filterUrl.getWhitePaths().contains(path)){return chain.filter(exchange);}//获取请求头String token = request.getHeaders().getFirst("token");if(StringUtils.hasText(token)&&"admin".equals(token)){ //查看redis中是否存在该tokenreturn chain.filter(exchange);//放行}//json数据Map<String, Object> map = new HashMap<>();map.put("msg", "未登录");map.put("code", 403);//3.3作JSON转换byte[] bytes = JSON.toJSONString(map).getBytes(StandardCharsets.UTF_8);//3.4调用bufferFactory方法,生成DataBuffer对象DataBuffer buffer = response.bufferFactory().wrap(bytes);//4.调用Mono中的just方法,返回要写给前端的JSON数据return response.writeWith(Mono.just(buffer));}//Ordered:优先级 值越小 优先级越高@Overridepublic int getOrder() {return 0;}
}
4.解决跨域问题🥝
第一种方式创建实体类

package com.lzq.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
import org.springframework.web.util.pattern.PathPatternParser;import java.util.Date;@Configuration
public class CorConfig {//处理跨域@Beanpublic CorsWebFilter corsFilter() {CorsConfiguration config = new CorsConfiguration();config.addAllowedMethod("*");config.addAllowedOrigin("*");config.addAllowedHeader("*");UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());source.registerCorsConfiguration("/**", config);return new CorsWebFilter(source);}
}
第二种方式在配置文件中编写

server:port: 81
spring:application:name: gateway #服务名称cloud:nacos:discovery:server-addr: localhost:8848 #nacos地址gateway:globalcors:add-to-simple-url-handler-mapping: truecors-configurations:'[/**]': #拦截的请求allowedOrigins: #允许跨域的请求- "http://localhost:8080"allowedMethods: #运行跨域的请求方式- "GET"- "POST"- "DELETE"- "PUT"- "OPTIONS"allowedHeaders: "*" #允许请求中携带的头信息allowedCredentials: true #是否允许携带cookiemaxAge: 36000 #跨域检测的有效期,单位s相关文章:
Gateway自定义过滤器——全局过滤器
一、什么是全局过滤器🍉 首先,我们要知道全局过滤器其实是特殊路由过滤器(特殊的GatewayFilter),会有条件地作用于所有路由。 为什么要自定义全局过滤器?就好比是看大门的保安大叔,平时主要是做好进出大门外来人员登记…...
Android App的几个核心概念
Application启动 点击桌面图标启动App(如下流程图) 针对以上流程图示: ActivityManagerService#startProcessLocked()Process#start()ActivityThread#main(),入口分析的地方ActivityThread#attach(),这个里面的逻辑很核心 ActivityManagerS…...
window10安装telnet
1、打开控制面板 2、点击程序和功能 3、点击启用或关闭Windows功能 4、选中Telnet客户端,然后点击确定,然后就可以使用telnent 主机 端口来查看本地是否能连通该主机的该端口。...
大厂sql真题讲解(黑马)
2023 http://yun.itheima.com/open/853.html | 面试宝典-如何备战大厂SQL真题 http://yun.itheima.com/open/858.html | 面试宝典–大厂必考知识开窗函数 http://yun.itheima.com/open/864.html | 面试宝典-详解美团SQL真题 http://yun.itheima.com/open/868.html | 图解大…...
SpringBoot整合EasyExcel实现读操作
😊 作者: 一恍过去 💖 主页: https://blog.csdn.net/zhuocailing3390 🎊 社区: Java技术栈交流 🎉 主题: SpringBoot整合EasyExcel实现读操作 ⏱️ 创作时间: 2023年…...
go mod 设置国内源 windows 环境 win10
启用 go module 功能 go env -w GO111MODULEon 配置 goproxy 变量 go env -w GOPROXYhttps://goproxy.cn,direct 下载包就行了,速度飞快 go mod tidy 检测 goproxy 是否配置好 运行 go env | findstr goproxy 查看 goproxy Go module 从 Go v1.12 版本开始存在&a…...
智能决策支持系统实现的关键技术分析
1.模 型 中 的 关 键 因 素 。 在 按 本 模 型 研 究 开 发 系 统 时 ,应 当 着 重 考 虑 以 下 几 个 因 素 : (1)设 备 保 护 需 求 计 划 。 保 护 需 求 包 括 了 人 员 、 物 质 、 财 务 等 各项 因 素 ; (2)考 虑 设 备 运行 及维修的 历史数据。 这是进 行 模 型 选 择…...
OSS对象存储后端实现+Vue实现图片上传【基于若依管理系统开发】
文章目录 基本介绍术语介绍图片上传方式介绍普通上传用户直传应用服务器签名后直传 OSS对象存储后端实现maven配置文件配置类ServiceController 图片上传前端图片上传组件api页面使用组件组件效果 基本介绍 术语介绍 Bucket(存储空间):用于…...
人工智能学习目录
1、人工智能-电脑如何像人一样思考? 从发展历史到人工智能的应用案例,再到人工智能本质是数学问题,从房价预测问题提出损失函数由参数导致,再由损失函数的最优值入手引入梯度下降法,最后到多参数方程的最优求解。 人工…...
Vue单页面实现el-tree el-breadcrumb功能、el-tree右键点击树节点展示菜单功能、树节点编辑节点字段名称功能
(1) 点击el-tree节点 使用el-breadcrumb展示选中树节点及父项数据 重点:handleNodeClick方法、getTreeNode方法 (2) 选择el-breadcrumb-item设置el-tree节点选中 必须设置属性: current-node-key"currentNodeKey" 、 node-key"id" 重点: 设置…...
C++核心编程之函数高级使用
目录 一、函数的默认参数 二、函数占位参数 三、函数重载 四、函数重载-注意事项 一、函数的默认参数 在C中,函数的形参列表中的形参是可以有默认值的 语法:返回值类型 函数名 (参数默认值){} 示例1: #includ…...
如何创建智能合约游戏系统
区块技术的发展,智能合约成为了一个热门话题。智能合约是一种基于区块技术的自动化合约,它可以自动执行合同中规定的条款,从而实现去中心化的信任和价值传递。在游戏领域,智能合约可以让玩家在游戏中实现各种交易和交互࿰…...
如何用rust实现一个异步channel
目录 前言思路实现功能代码实现 测试先引测试版包测试代码结果与分析思考 尾语 前言 使用通信来共享内存,而不是通过共享内存来通信 上面这句话,是每个go开发者在 处理多线程通信时 的座右铭,go甚至把实现这个理念的channel直接焊在编译器里&…...
gitee上传项目到仓库
目录 一些常用的Git命令切换到其他盘符:列出目录下的所有文件:以树状图的形式显示目录下的文件和子目录:返回上一层目录:写的C#代码文件上传到新建的Git仓库中,可以按照以下步骤进行操作:出现的错误: 一些常…...
day27 贪心算法
1.什么是贪心? 比如10张钞票,有1,5,20,100等面额,取五张,如何取得到数额最多的钱?每次取面额最大的那张钞票;就是每个阶段的局部最优;全局最优就是最后拿到的…...
Java实现字符串反转
起因 自己在刷题的过程中,想把一个字符串翻转一下,便写了下面的代码: String str "abcd";str str.reverse();发现行不通,这是为什么呢? 分析 在Java中,字符串是不可变的对象,这意…...
vue - 常见的性能优化
文章目录 vue使用中常见的性能优化1, v-for 遍历避免同时使用 v-if2, 如果需要使用v-for给每项元素绑定事件时 可以使用事件代理**3, 一些数据不做响应式4,一些页面采用keep-alive缓存组件5,第三方UI库按需导入6&#…...
微服务系列文章 之 Nginx服务状态监控的方法
在Nginx的插件模块中有一个模块stub_status可以监控Nginx的一些状态信息,默认安装可能没有这个模块,手动编译的时候加一下即可。 1. 模块安装 先使用命令查看是否已经安装这个模块: [rootihxb123Z nginx]# ./nginx -V (V大写会显示版本号和…...
【网络系统集成】路由器实验
1.实验名称:路由器RIP协议配置 2.实验目的 在PacketTracer中进行模拟实验,配置RIP协议,验证RIP协议更新时间及路由状态变化,加深对路由器RIP协议相关知识的理解与掌握。 3.实验内容 (1)拓扑结构图 (2)ip地址分配与端口分配...
【mac 安装Miniconda】
1.下载Miniconda 注意mac是什么版本,m1下载m1版本 https://docs.conda.io/en/latest/miniconda.html#macos-installers 2.安装Miniconda 在下载文件所在目录下打开终端,输入一下命令: bash Miniconda3-latest-MacOSX-x86_64.sh 一路回车&…...
变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析
一、变量声明设计:let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性,这种设计体现了语言的核心哲学。以下是深度解析: 1.1 设计理念剖析 安全优先原则:默认不可变强制开发者明确声明意图 let x 5; …...
SkyWalking 10.2.0 SWCK 配置过程
SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外,K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案,全安装在K8S群集中。 具体可参…...
Java 8 Stream API 入门到实践详解
一、告别 for 循环! 传统痛点: Java 8 之前,集合操作离不开冗长的 for 循环和匿名类。例如,过滤列表中的偶数: List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...
vue3 字体颜色设置的多种方式
在Vue 3中设置字体颜色可以通过多种方式实现,这取决于你是想在组件内部直接设置,还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法: 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现
摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序,以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务,提供稳定高效的数据处理与业务逻辑支持;利用 uniapp 实现跨平台前…...
《基于Apache Flink的流处理》笔记
思维导图 1-3 章 4-7章 8-11 章 参考资料 源码: https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...
python执行测试用例,allure报乱码且未成功生成报告
allure执行测试用例时显示乱码:‘allure’ �����ڲ����ⲿ���Ҳ���ǿ�&am…...
重启Eureka集群中的节点,对已经注册的服务有什么影响
先看答案,如果正确地操作,重启Eureka集群中的节点,对已经注册的服务影响非常小,甚至可以做到无感知。 但如果操作不当,可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...
Python 实现 Web 静态服务器(HTTP 协议)
目录 一、在本地启动 HTTP 服务器1. Windows 下安装 node.js1)下载安装包2)配置环境变量3)安装镜像4)node.js 的常用命令 2. 安装 http-server 服务3. 使用 http-server 开启服务1)使用 http-server2)详解 …...
