微服务实战系列之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


在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/602960.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

最大子数组和【DP】

Problem: 53. 最大子数组和 文章目录 思路 & 解题方法复杂度Code 思路 & 解题方法 以前常见的线性DP&#xff0c;题目简单&#xff0c;可以不需要用数组来存储dp的值。 复杂度 时间复杂度: 添加时间复杂度, 示例&#xff1a; O ( n ) O(n) O(n) 空间复杂度: 添加空间…

Java Swing手搓童年坦克大战游戏(II)

文章目录 0.初衷1.创建游戏窗口2.创建坦克3.实现坦克移动和发射炮弹4.创建地图4.1关于地图瓦片的尺寸遇到的问题 5.坦克与障碍物的碰撞处理5.1碰撞检测5.2坦克与地图中的瓦片碰撞5.3坦克相互碰撞5.4坦克碰见炮弹5.5坦克拐弯 6.道具6.1星星6.2炸弹6.3钟表6.4城堡6.5坦克6.6无敌圈…

《3D数学基础-图形和游戏开发》阅读笔记 | 3D数学基础 (学习中 1.6更新)

文章目录 3D数学基础矢量/向量什么是向量点与矢量的关系 向量基础运算 向量加法向量基础运算 数乘 线性组合 - 坐标系的基如果选择不同的基向量会怎么样&#xff1f;- 张成(Span)的空间三维向量的张成空间线性相关与线性相关 矩阵与线性变换矩阵-几何意义线性变换矩阵乘法与线性…

业务数据技术中台概念与相互关系

随着企业数字化转型和发展模式的转变,企业的应用架构建设模式主要为数据+中台(平台)+应用,这里的企业就涵盖互联网大企业和传统企业,大家都在开展必做的事情,即数字化时代的企业数字化转型 。同时,正好最近在做顶层设计和数字化转型整体应用架构设计,就梳理了一下中台发展…

Kafka消息存储

一、层次结构 具体到某个broker上则是, 数据目录/分区名/日志相关文件集合。其中日志文件集合内包括.log文件, index索引文件和.timeindex时间戳索引文件。 二、.log 结构 .log中记录具体的消息。一般消息由header和body组成, 这点儿在Kafka消息中也同样适用。 message MES…

qt自定义控件的封装

刚学了一个很有意思的东西,前面学了list,Tree,Table三大控件和一部分常用基础控件,但感觉没啥意思,就是用别人的直接用,刚学了一个自定义控件的封装,流程如下: 想把两个不相关的组件封装在一块,直接用ui不行,所以先新添加了qt设计师页面,新添加了一个SmallWidget *ui 在smal…

Mongodb使用指定索引删除数据

回顾Mongodb删除语法 db.collection.deleteMany(<filter>,{writeConcern: <document>,collation: <document>,hint: <document|string>} ) 删除语法中&#xff0c;除了指定过滤器外&#xff0c;还可以指定写入策略&#xff0c;字符序和使用的索引。 …

【Leetcode】230. 二叉搜索树中第K小的元素

一、题目 1、题目描述 给定一个二叉搜索树的根节点 root ,和一个整数 k ,请你设计一个算法查找其中第 k 个最小元素(从 1 开始计数)。 示例1: 输入:root = [3,1,4,null,2], k = 1 输出:1示例2: 输入:root = [5,3,6,2,4,null,null,1], k = 3 输出:3提示: 树中…

字节跳动基础架构SRE-Copilot获得2023 CCF国际AIOps挑战赛冠军

近日&#xff0c;2023 CCF国际AIOps挑战赛决赛暨“大模型时代的AIOps”研讨会在北京成功举办&#xff0c;活动吸引了来自互联网、运营商、科研院所、高校、软硬件厂商等领域多名专家学者参与&#xff0c;为智能运维的前沿学术研究、落地生产实践打开了新思路。决赛中&#xff0…

看图识熊(二)

使用Tools for AI封装onnx模型并推理 进行这一步之前&#xff0c;请确保已正确安装配置了Visual Studio 2017 和 Microsoft Visual Studio Tools for AI环境。 项目的代码也可以在这里找到&#xff0c;下面的步骤是带着大家从头到尾做一遍。 界面设计 创建Windows窗体应用(…

双向数据绑定详细解析(超详细)

文章目录 一、什么是双向绑定二、双向绑定的原理是什么理解ViewModel 三、实现双向绑定实现编译Compile依赖收集 参考文献 一、什么是双向绑定 我们先从单向绑定切入单向绑定非常简单&#xff0c;就是把Model绑定到View&#xff0c;当我们用JavaScript代码更新Model时&#xf…

QML —— 使用Qt虚拟键盘示例(附完整源码)

示例效果 使用"虚拟键盘"注意 &#xff08;例子的Qt版本:5.12.4&#xff09; 注意一&#xff1a;      /* 必须在main.cpp开始处加入如下代码&#xff0c;否则无法使用"虚拟键盘" */      qputenv(“QT_IM_MODULE”,QByteArray(“qtvirtualkeybo…

苹果MacOS12系统 Monterey最新正式版下载 MacOS12系统镜像包

macOS 12 Monterey是苹果公司最新发布的操作系统&#xff0c;为Mac用户带来了更强大、更智能的功能和体验。 这个版本引入了许多令人兴奋的新特性&#xff0c;其中包括革命性的Universal Control功能&#xff0c;让你可以无缝地在Mac和iPad之间进行操作。只需将iPad放在Mac附近…

OpenCV的安装和vscode的配置

在图像处理领域&#xff0c;OpenCV的使用是必不可少的&#xff0c;这里介绍一下OpenCV的安装及其在vscode中的配置 1.OpenCV的安装 &#xff08;1&#xff09;安装依赖 sudo apt-get install build-essentialsudo apt-get install cmake git libgtk2.0-dev pkg-config libavc…

GEE——土地利用分类种两个矢量集合中不同列进行相减的方式(利用join进行连接处理)

问题: 我有两个具有相同 ID 的特征集,我想从第二个特征集中减去第一个特征集的表格单元格。 我使用了这个函数,但它计算的是表 1 中第一个元素与表 2 中其他元素的减法。 我想逐个单元格计算减法。第一个表格中 id 为 1 的单元格减去第二个表格中 id 为 1 的单元格,2x2、…

主线程退出后子线程是否还会正常运行?

问题&#xff1a; 父子线程的关系 今天突然有感而发&#xff0c; 想要来探讨一下主线程和子线程之间的关系。 例一&#xff1a;子线程执行时间较父线程慢 public class ThreadTest {public static void main(String[] args) {// 测试主线程 和 子线程Thread sonThread new …

Python 教程 01:Python 简介及发展历史

ℹ️说明&#xff1a;关于本教程的一些约定 ① 教程后有&#xff08;选读&#xff09;的表示此教程为扩展内容&#xff0c;选读&#xff1b; ② 教程中涉及到的代码片段有时候并非代码块&#xff0c;而是图片&#xff0c;这是防止初学者直接复制代码粘贴的行为&#xff0c;想必…

应用OpenCV绘制箭头

绘制箭头函数 方法&#xff1a;函数cv2.arrowedLine( ) 语法格式&#xff1a;cv2.arrowedLine(img, pt1, pt2, color[, thickness[, line_type[, shift[, tipLength]]]]) 参数说明&#xff1a; img&#xff1a;要画的直线所在的图像&#xff0c;也称为画布。。 pt1&#x…

【CSS】文字描边的三种实现方式

目录 1. 可行的几种方式1.1. text-shadow 描边代码优缺点 1.2. text-stroke 描边实现优缺点 1.3. svg 描边实现优缺点 总结 1. 可行的几种方式 text-shadow–webkit-text-strokesvg 1.1. text-shadow 描边 MDN text-shadow 代码 <div class"text stroke">…

Ubuntu软件和vmware下载

https://cn.ubuntu.com/download/desktop VMware 中国 - 交付面向企业的数字化基础 | CN