微服务实战系列之Filter
前言
Filter,又名过滤器,当然不是我们日常中见到的,诸如此类构件:

而应该是微服务中常使用的,诸如此类(图片来自官网,点击可查看原图):

一般用于字符编码转换,日志处理等场景。而我们今天提到的Filter是基于springcloud gateway而言的。
一、Gateway Filter
1. 按生命周期划分
通过springcloud gateway的工作原理图,我们可以发现,过滤器在数据的请求和返回的过程中发挥它应有的作用。此类过滤器生命周期有两类:
| 过滤器阶段 | 过滤器作用 |
|---|---|
| Pre-req | 业务逻辑请求前(pre-request),完成相关操作 |
| Post-req | 业务逻辑请求后(post-request),完成相关操作 |
2. 按职责范围划分
| 过滤器名称 | 过滤器简介 |
|---|---|
| GateWayFilter | 单一过滤器,即仅可完成单一功能的Filter,一般可建多个 |
| GlobalFilter | 全局过滤器,可完成所有路由功能的Filter,一般只建1个 |
其他内容可参考官网,这里不再赘述。如需请速戳:springcloud gateway。
当然不管是什么生命周期,还是什么职责范围,过滤器都会按照指定的路由执行,否则那不乱成一锅粥了。
因此,每个过滤器都应指定一个顺序Order值。
二、Gateway Filter Order
一句话总结:Order值越小,优先级越高,执行越靠前。
以下是springcloud gateway filter中的order定义:
public interface Ordered {/*** Useful constant for the highest precedence value.* @see java.lang.Integer#MIN_VALUE*/int HIGHEST_PRECEDENCE = Integer.MIN_VALUE;/*** Useful constant for the lowest precedence value.* @see java.lang.Integer#MAX_VALUE*/int LOWEST_PRECEDENCE = Integer.MAX_VALUE;/*** Get the order value of this object.* <p>Higher values are interpreted as lower priority. As a consequence,* the object with the lowest value has the highest priority (somewhat* analogous to Servlet {@code load-on-startup} values).* <p>Same order values will result in arbitrary sort positions for the* affected objects.* @return the order value* @see #HIGHEST_PRECEDENCE* @see #LOWEST_PRECEDENCE*/int getOrder();}
而我们在使用的过程中,一般这样定义顺序:
@Component
public class TestGlobalFilter implements GlobalFilter, Ordered {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {return chain.filter(exchange);}@Overridepublic int getOrder() {return 123;}
}
三、问题案例
因为我们在项目开发过程中, 为完成某些特定功能,会经常使用过滤器,所以难免遇到一些问题。而今天博主重点介绍其中的一个问题:请求体丢失,即只能消费一次的问题。
废话无需多言,直接参考以下代码,即可满足你的需要:
1. 缓存requestbody
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.core.io.buffer.DataBufferUtils;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;/*** 定义一个全局过滤器,实现requestbody缓存* @date 2024/01/07 09:06*/
@Component
public class ReqGlobalFilter implements Ordered, GlobalFilter {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {if (exchange.getRequest().getHeaders().getContentType() == null) {return chain.filter(exchange);} else {return DataBufferUtils.join(exchange.getRequest().getBody()).flatMap(dataBuffer -> {DataBufferUtils.retain(dataBuffer);Flux<DataBuffer> cachedFlux = Flux.defer(() -> Flux.just(dataBuffer.slice(0, dataBuffer.readableByteCount())));ServerHttpRequest mutatedRequest = new ServerHttpRequestDecorator(exchange.getRequest()) {@Overridepublic Flux<DataBuffer> getBody() {return cachedFlux;}};return chain.filter(exchange.mutate().request(mutatedRequest).build());});}}@Overridepublic int getOrder() {return -10000;//也可设置为最高优先级}
}
2. 获取requestbody
在其他过滤器中,引用以下代码,实现requestbody获取:
private String resolveBodyFromRequest(ServerHttpRequest serverHttpRequest){// 获取请求体Flux<DataBuffer> body = serverHttpRequest.getBody();AtomicReference<String> bodyRef = new AtomicReference<>();body.subscribe(buffer -> {CharBuffer charBuffer = StandardCharsets.UTF_8.decode(buffer.asByteBuffer());DataBufferUtils.release(buffer);bodyRef.set(charBuffer.toString());});return bodyRef.get();}
结语
Filter是完成业务逻辑前或后应有操作的必要环节,也是实现统一服务的典型武器,所以我们应该了解它、学习它、掌握它。
好了,今日话题到此为止,下一篇是啥,继续期待!
历史回顾
-
微服务实战系列之API加密
-
微服务实战系列之Dubbo(下)
-
微服务实战系列之Dubbo(上)
-
微服务实战系列之ZooKeeper(实践篇)
-
微服务实战系列之ZooKeeper(下)
-
微服务实战系列之ZooKeeper(中)
-
微服务实战系列之ZooKeeper(上)
-
微服务实战系列之MQ
-
微服务实战系列之通信
-
微服务实战系列之J2Cache
-
微服务实战系列之Cache(技巧篇)
-
微服务实战系列之MemCache
-
微服务实战系列之EhCache
-
微服务实战系列之Redis
-
微服务实战系列之Cache
-
微服务实战系列之Nginx(技巧篇)
-
微服务实战系列之Nginx
-
微服务实战系列之Feign
-
微服务实战系列之Sentinel
-
微服务实战系列之Token
-
微服务实战系列之Nacos
-
微服务实战系列之Gateway
-
微服务实战系列之加密RSA
-
微服务实战系列之签名Sign

相关文章:
微服务实战系列之Filter
前言 Filter,又名过滤器,当然不是我们日常中见到的,诸如此类构件: 而应该是微服务中常使用的,诸如此类(图片来自官网,点击可查看原图): 一般用于字符编码转换…...
使用GPT大模型调用工具链
本文特指openai使用sdk的方式调用工具链。 安装openai pip install openai export OPENAI_API_KEY"YOUR OPENAI KEY" 定义工具函数 from openai import OpenAI import jsonclient OpenAI() #工具函数 def get_current_weather(location, unit"fahrenheit&q…...
C语言实现bmp图像底层数据写入与创建
要用C语言实现bmp图像底层数据写入进而创建一张bmp图像,需要对bmp图像文件格式非常了解,如果不太熟悉bmp图像文件格式请先移步bmp图像文件格式超详解 创建bmp图像文件的方式有很多,比如用halcon,用qt,这些都是把已经画…...
基于BP神经网络的定位算法,基于BP神经网络定位预测
目录 摘要 BP神经网络参数设置及各种函数选择 参数设置 训练函数 传递函数 学习函数 性能函数 显示函数 前向网络创建函数 BP神经网络训练窗口详解 训练窗口例样 训练窗口四部详解 基于BP神经网络的定位算法,基于BP神经网络定位预测 代码下载:基于BP神经网络的定位算法,基于…...
Java Http各个请求类型详细介绍
1. 前言 在Spring Boot框架中,HTTP请求类型是构建Web应用程序的重要组成部分。常见的请求类型包括GET、POST、PUT和DELETE,每种类型都有其特定的用途和特点。本文将详细比较这四种请求类型,帮助您在开发过程中做出明智的选择。 2. GET请求…...
python函数装饰器参数统计调用时间和次数
1 python函数装饰器参数统计调用时间和次数 python在函数装饰器外层定义一个函数生成封闭作用域来保存装饰器入参,供装饰器使用。 1.1 装饰器统计调用时间和次数 描述 通过类的可调用实例装饰器来统计函数每次调用时间和总调用时间,以及调用次数。 …...
机器学习之集成学习AdaBoost
概念 AdaBoost(Adaptive Boosting)是一种迭代的集成学习算法,其主要目标是通过组合多个弱学习器来创建一个强大的模型。以下是AdaBoost算法的主要步骤: 初始化样本权重: 为每个训练样本分配相等的权重,通常设为 w i = 1 N w_i = \frac{1}{N} w...
行云部署成长之路 -- 慢 SQL 优化之旅 | 京东云技术团队
当项目的SQL查询慢得像蜗牛爬行时,用户的耐心也在一点点被消耗,作为研发,我们可不想看到这样的事。这篇文章将结合行云部署项目的实践经验,带你走进SQL优化的奇妙世界,一起探索如何让那些龟速的查询飞起来!…...
Windows权限提升
0x01 简介 提权可分为纵向提权与横向提权: 纵向提权:低权限角色获得高权限角色的权限; 横向提权:获取同级别角色的权限。 Windows常用的提权方法有:系统内核溢出漏洞提权、数据库提权、错误的系统配置提权、组策略首…...
win系统搭建Minecraft世界服务器,MC开服教程,小白开服教程
Windows系统搭建我的世界世界服务器,Minecraft开服教程,小白开服教程,MC 1.19.4版本服务器搭建教程。 此教程使用 Mohist 1.19.4 服务端,此服务端支持Forge模组和Bukkit/Spigot/Paper插件,如果需要开其他服务端也可参…...
word2vec中的CBOW和Skip-gram
word2cev简单介绍 Word2Vec是一种用于学习词嵌入(word embeddings)的技术,旨在将单词映射到具有语义关联的连续向量空间。Word2Vec由Google的研究员Tomas Mikolov等人于2013年提出,它通过无监督学习从大规模文本语料库中学习词汇…...
在ios上z-index不起作用问题的总结
最近在维护一个H5老项目时,遇到一个问题,就是在ios上z-index不起作用,在安卓上样式都是好的。 项目的架构组成是vue2.x vux vuex vue-router等 用的UI组件库是vux 在页面中有一个功能点,就是点选择公司列表的时候,会…...
力扣labuladong一刷day59天动态规划
力扣labuladong一刷day59天动态规划 文章目录 力扣labuladong一刷day59天动态规划一、509. 斐波那契数二、322. 零钱兑换 一、509. 斐波那契数 题目链接:https://leetcode.cn/problems/fibonacci-number/description/ 思路:这是非常典型的一道题&#x…...
pyenv环境找不到sqlite:No module named _sqlite3
前言 一般遇到这个问题都在python版本管理或者虚拟环境切换中遇到,主要有两个办法解决,如下: 解决方法1 如果使用的pyenv管理python环境时遇到没有_sqlite3 库,可以将当前pyenv的python环境卸载 pyenv uninstall xxx然后在系统…...
Histone H3K4me2 Antibody, SNAP-Certified™ for CUTRUN
EpiCypher是一家为表观遗传学和染色质生物学研究提供高质量试剂和工具的专业制造商。EpiCypher推出的CUT&RUN级别的Histone H3K4me2 Antibody符合EpiCypher的批次特异性SNAP-CertifiedTM标准,在CUT&RUN中具有特异性和高效的靶点富集。通过SNAP-CUTANA™K-Me…...
我用 Laf 开发了一个非常好用的密码管理工具
【KeePass 密码管理】是一款简单、安全简洁的账号密码管理工具,服务端使用 Laf 云开发,支持指纹验证、FaceID,N 重安全保障,可以随时随地记录我的账号和密码。 写这个小程序之前,在国内市场找了很多密码存储类的 App …...
windows项目部署
文章目录 一、项目部署1.1 先准备好文件1.2安装jdk1.3 配置环境1.4 安装tomcat1.5 MySQL安装本机测试的话:远程连接测试 1.6 项目部署 一、项目部署 1.1 先准备好文件 1.2安装jdk 下一步 下一步 下一步 1.3 配置环境 变量名:JAVA_HOME 变量值:jdk的…...
http首部
1. htttp 报文首部 报文结构为:首部 空行(CRLF)主体 在请求中 http报文首部由请求方法,URI,http版本,首部字段等构成 在响应中:状态码,http版本,首部字段3部分构成 2…...
2024.1.8 Day04_SparkCore_homeWork
目录 1. 简述Spark持久化中缓存和checkpoint检查点的区别 2 . 如何使用缓存和检查点? 3 . 代码题 浏览器Nginx案例 先进行数据清洗,做后续需求用 1、需求一:点击最多的前10个网站域名 2、需求二:用户最喜欢点击的页面排序TOP10 3、需求三&#x…...
09.简单工厂模式与工厂方法模式
道生一,一生二,二生三,三生万物。——《道德经》 最近小米新车亮相的消息可以说引起了不小的轰动,我们在感慨SU7充满土豪气息的保时捷设计的同时,也深深的被本土品牌的野心和干劲所鼓舞。 今天我们就接着这个背景&…...
C++初阶-list的底层
目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...
React hook之useRef
React useRef 详解 useRef 是 React 提供的一个 Hook,用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途,下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...
Java 8 Stream API 入门到实践详解
一、告别 for 循环! 传统痛点: Java 8 之前,集合操作离不开冗长的 for 循环和匿名类。例如,过滤列表中的偶数: List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...
从零实现富文本编辑器#5-编辑器选区模型的状态结构表达
先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...
学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1
每日一言 生活的美好,总是藏在那些你咬牙坚持的日子里。 硬件:OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写,"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...
Spring AI 入门:Java 开发者的生成式 AI 实践之路
一、Spring AI 简介 在人工智能技术快速迭代的今天,Spring AI 作为 Spring 生态系统的新生力量,正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务(如 OpenAI、Anthropic)的无缝对接&…...
自然语言处理——Transformer
自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效,它能挖掘数据中的时序信息以及语义信息,但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN,但是…...
OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在 GPU 上对图像执行 均值漂移滤波(Mean Shift Filtering),用于图像分割或平滑处理。 该函数将输入图像中的…...
使用 SymPy 进行向量和矩阵的高级操作
在科学计算和工程领域,向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能,能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作,并通过具体…...
【Redis】笔记|第8节|大厂高并发缓存架构实战与优化
缓存架构 代码结构 代码详情 功能点: 多级缓存,先查本地缓存,再查Redis,最后才查数据库热点数据重建逻辑使用分布式锁,二次查询更新缓存采用读写锁提升性能采用Redis的发布订阅机制通知所有实例更新本地缓存适用读多…...
