Springcloudgateway如何在全局过滤器中获得请求体和响应体

需要使用请求装饰类和响应装饰类,把请求体和响应体保存一下,再在全局Post过滤器里面获得该请求体。

 请求装饰类

package com.chilun.apiopenspace.gateway.filter;import com.chilun.apiopenspace.gateway.Utils.LogCacheMap;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;import java.nio.charset.StandardCharsets;/*** @author 齿轮* @date 2024-02-29-17:51*/
@Slf4j
public class LoggingRequestDecorator extends ServerHttpRequestDecorator {private final String uuid;private final DataBufferFactory bufferFactory;public LoggingRequestDecorator(ServerHttpRequest delegate, ServerWebExchange exchange, String uuid) {super(delegate);this.bufferFactory = exchange.getResponse().bufferFactory();this.uuid = uuid;}@NotNull@Overridepublic Flux<DataBuffer> getBody() {Flux<DataBuffer> originalBody = super.getBody();return originalBody.map(dataBuffer -> {byte[] content = new byte[dataBuffer.readableByteCount()];dataBuffer.read(content);// 将请求体数据转换为字符串,并保存到缓存中String requestBody = new String(content, StandardCharsets.UTF_8);log.info("Request Body: " + requestBody);LogCacheMap.saveRequest(uuid, requestBody);//重新包装了DataBuffer,所以要释放原始的DataBufferDataBufferUtils.release(dataBuffer);// 返回新的DataBufferreturn bufferFactory.wrap(content);});}
}

响应装饰类

package com.chilun.apiopenspace.gateway.filter;import com.chilun.apiopenspace.gateway.Utils.LogCacheMap;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;import java.nio.charset.StandardCharsets;/*** @author 齿轮* @date 2024-02-29-17:51*/
@Slf4j
public class LoggingResponseDecorator extends ServerHttpResponseDecorator {private final DataBufferFactory bufferFactory;private final String uuid;public LoggingResponseDecorator(ServerHttpResponse delegate, String uuid) {super(delegate);this.bufferFactory = delegate.bufferFactory();this.uuid = uuid;}@Overridepublic Mono<Void> writeWith(org.reactivestreams.Publisher<? extends org.springframework.core.io.buffer.DataBuffer> body) {
//        if (getStatusCode().is2xxSuccessful()) {
//            //正常情况直接返回
//            return super.writeWith(body);
//        } else if (body instanceof Flux) {//异常情况保存响应Flux<? extends DataBuffer> fluxBody = Flux.from(body);return super.writeWith(fluxBody.buffer().map(dataBuffers -> {DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory();DataBuffer join = dataBufferFactory.join(dataBuffers);byte[] content = new byte[join.readableByteCount()];join.read(content);DataBufferUtils.release(join);String responseBody = new String(content, StandardCharsets.UTF_8);log.info("response body: {}", responseBody);LogCacheMap.saveResponse(uuid, responseBody);byte[] uppedContent = responseBody.replaceAll(":null", ":\"\"").getBytes(StandardCharsets.UTF_8);return bufferFactory.wrap(uppedContent);}));}return super.writeWith(body);}
}

 用到的自定义工具类

package com.chilun.apiopenspace.gateway.Utils;import java.util.HashMap;/*** @author 齿轮* @date 2024-02-29-18:52*/public class LogCacheMap {public static HashMap<String, String> LogMap = new HashMap<>();public static void saveRequest(String uuid, String request) {LogMap.put(uuid + "request", request);}public static String getRequest(String uuid) {return LogMap.remove(uuid + "request");}public static void saveResponse(String uuid, String response) {LogMap.put(uuid + "response", response);}public static String getResponse(String uuid) {return LogMap.remove(uuid + "response");}
}

全局过滤器类

package com.chilun.apiopenspace.gateway.filter;import com.chilun.apiopenspace.gateway.Utils.LogCacheMap;
import com.chilun.apiopenspace.gateway.service.AccessLogService;
import com.google.common.base.Joiner;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;import javax.annotation.Resource;
import java.util.UUID;/*** @author 齿轮* @date 2024-02-28-14:35*/
@Slf4j
@Component
public class LogFilter implements GlobalFilter, Ordered {@ResourceAccessLogService logService;@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {String uuid = UUID.randomUUID().toString();//注入requestDecorator、responseDecorator用于获得请求体、响应体ServerHttpRequestDecorator requestDecorator = new LoggingRequestDecorator(exchange.getRequest(), exchange, uuid);ServerHttpResponseDecorator responseDecorator = new LoggingResponseDecorator(exchange.getResponse(), uuid);return chain.filter(exchange.mutate().request(requestDecorator).response(responseDecorator).build()).then(Mono.just(exchange)).map(serverWebExchange -> {if (serverWebExchange.getResponse().getStatusCode().is2xxSuccessful()) {logService.sendCommonLog(true);logService.sendRightLog(LogCacheMap.getRequest(uuid), LogCacheMap.getResponse(uuid));} else {logService.sendCommonLog(false);logService.sendErrorLog(LogCacheMap.getRequest(uuid), LogCacheMap.getResponse(uuid));}return serverWebExchange;}).then();}@Overridepublic int getOrder() {return Ordered.HIGHEST_PRECEDENCE;}
}

如果也是使用Map存储请求体,注意用不到请求体/响应体后删除他们,避免内存溢出。

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

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

相关文章

Sora技术原理解析

1.Sora简介 Sora是一个基于大规模训练的文本控制视频生成扩散模型。 Sora能够生成高达1分钟的高清视频&#xff0c;涵盖广泛的视觉数据类型和分辨率。 Sora使用简单的文本描述&#xff0c;使得视频创作变得前所未有的简单和高效。 Sora的一些能力&#xff1a; Text-to-video…

windows server mysql 数据库停止 备份 恢复全流程操作方法

一,mysql备份 mysql最好是原工程文件备份.不需要sql查询的方式备份.安全高效. 比如,安装php与mysql组合后,我的mysql文件保存在: D:\phpstudy_pro\Extensions\MySQL5.7.26\data\dux 我只需要复制一份,保存起来就行. 二,mysql恢复 怎么恢复呢.我们一般是只恢复其中一个表,则找…

一个具有强大PDF处理能力的.Net开源项目

PDF具有跨平台、可读性强、不可修改性、无需特定阅读软件、内容安全等好处&#xff0c;在工作中经常都会用到。 所以&#xff0c;我们在项目开发中&#xff0c;经常需要生成PDF的文件&#xff0c;或者把Html、Xml等文件转化为PDF格式。 今天给大家推荐一个具有PDF处理能力的.…

优思学院|质量工程师需要学习什么软件?

初入职质量工程师的朋友常常会问&#xff1a;质量工程师需要学习什么软件&#xff1f;在质量控制和管理的世界里&#xff0c;拥有强大的数据分析工具是走向成功的关键&#xff0c;因此&#xff0c;对于质量工程师来说&#xff0c;掌握正确的软件不仅能提升工作效率&#xff0c;…

lv20 QT对话框3

1 内置对话框 标准对话框样式 内置对话框基类 QColorDialog, QErrorMessage QFileDialog QFontDialog QInputDialog QMessageBox QProgressDialogQDialog Class帮助文档 示例&#xff1a;各按钮激发对话框实现基类提供的各效果 第一步&#xff1a;实现组件布局&…

Go 如何控制并发的goroutine数量?

为什么要控制goroutine并发的数量&#xff1f; 在开发过程中&#xff0c;如果不对goroutine加以控制而进行滥用的话&#xff0c;可能会导致服务整体崩溃。比如耗尽系统资源导致程序崩溃&#xff0c;或者CPU使用率过高导致系统忙不过来。 用什么方法控制goroutine并发的数量&a…

Pyhton的组合数据类型

归纳编程学习的感悟&#xff0c; 记录奋斗路上的点滴&#xff0c; 希望能帮到一样刻苦的你&#xff01; 如有不足欢迎指正&#xff01; 共同学习交流&#xff01; &#x1f30e;欢迎各位→点赞 &#x1f44d; 收藏⭐ 留言​&#x1f4dd; 生命对某些人来说是美丽的&#xff0c…

尝鲜18倍速大模型Groq和世界第二AI Mistral(Le Chat)

01 尝鲜 中午,一边吃饭,一边尝试一下最新的AI:Groq,它使用了重新设计的LPU,据说比英伟达的GPU快了18倍。 运行了开源的Mixtral-8x7b模型,屏幕上的文字回复几乎是瞬间的,那种速度感,让人心跳加速。 接着,我尝试了来自欧洲的新贵——Mistral AI的Le Chat。 这个三天前…

python学习笔记-内置异常

概述 Python 中的异常&#xff08;Exception&#xff09;是指在程序执行过程中遇到的错误或异常情况。当程序出现异常时&#xff0c;解释器会停止当前代码的执行&#xff0c;并试图找到匹配的异常处理器来处理异常。如果没有找到合适的异常处理器&#xff0c;程序就会终止并打…

go并发模式之----阻塞/屏障模式

常见模式之一&#xff1a;阻塞/屏障模式 定义 顾名思义&#xff0c;就是阻塞等待所有goroutine&#xff0c;直到所有goroutine完成&#xff0c;聚合所有结果 使用场景 多个网络请求&#xff0c;聚合结果 大任务拆分成多个子任务&#xff0c;聚合结果 示例 package main ​…

go语言基础 -- 二维数组

二维数组 定义 先声明/定义&#xff0c;再赋值 var d2arr [4][6] int 以上二维数组有4个指针分别指向自己的地址空间&#xff0c;各个指针指向的地址空间也是连续的 也可以直接在声明的时候初始化&#xff0c;格式如下&#xff1a; var arr [2][2] int [2][2]{{0, 1}, {2, …

279.【华为OD机试真题】运输时间(贪心算法—JavaPythonC++JS实现)

🚀点击这里可直接跳转到本专栏,可查阅顶置最新的华为OD机试宝典~ 本专栏所有题目均包含优质解题思路,高质量解题代码(Java&Python&C++&JS分别实现),详细代码讲解,助你深入学习,深度掌握! 文章目录 一. 题目-运输时间二.解题思路三.题解代码Python题解代码…

试题 算法训练 车的放置

资源限制 内存限制&#xff1a;256.0MB C/C时间限制&#xff1a;1.0s Java时间限制&#xff1a;3.0s Python时间限制&#xff1a;5.0s 问题描述 在一个n*n的棋盘中&#xff0c;每个格子中至多放置一个车&#xff0c;且要保证任何两个车都不能相互攻击&#xff0c;有多少中…

配电房轨道式巡检机器人方案

一、应用背景 在变电站、配电房、开关站等各种室内变配电场所内&#xff0c;由于变配电设备的数量众多、可能存在各类安全隐患&#xff0c;为了保证用电的安全可靠&#xff0c;都要进行日常巡检。 但目前配电房人工巡检方式有以下主要问题&#xff1a; 巡检工作量大、成本高 …

linux ecs 挂载分区

# 展示盘 lsblk # nvme0n1 259:3 0 1.8T 0 disk # nvme1n1 259:0 0 1.8T 0 disk # nvme2n1 259:2 0 1.8T 0 disk # nvme3n1 259:1 0 1.8T 0 disk # 为nvme1n1创建一个新的分区 sudo fdisk /dev/nvme1n1 # 使用fdisk的命令序列&…

机器学习-1

文章目录 前言机器学习基本定义 练习题 前言 在本片开始将为大家介绍机器学习相关的知识点。 机器学习基本定义 夏天&#xff0c;我们通常会去水果店里买西瓜&#xff0c;我们看到一个根蒂蜷缩、敲起来声音浑浊的青绿色的西瓜&#xff0c;我们提着西瓜就去结账了&#xff0c;…

关于StartAI本地部署相关问题解答

很多小伙伴们都有接入自己本地SD的需求&#xff0c;对此小编整理了一些相关问题~ 一、本地部署相关条件 对于想要本地部署的小伙伴要了解&#xff0c;相对于使用StartAI试用引擎本地部署更加考验电脑硬件配置备噢~ 流畅使用要nvidia显卡&#xff0c;6g以上显存&#xff08;最…

Linux按键输入实验-测试新的设备树文件

一. 简介 前面一篇文章学习在设备树文件中创建按键的设备节点信息。文章地址如下: Linux键盘输入实验-创建按键的设备节点-CSDN博客 本文对创建了按键设备节点的设备树文件进行测试,确认按键的设备节点信息是否已创建好。 二. 测试创建的按键设备节点是否存在 1. 拷贝…

图解知识蒸馏

soft labels与soft predictions越接近越好&#xff0c;通过Loss Fn来实现&#xff0c;产生的数值叫做distillation loss&#xff0c;也叫soft loss。 hard label y与hard prediction越接近越好&#xff0c;通过Loss Fn来实现&#xff0c;产生的数值叫做student loss&#xff0c…

什么是VR虚拟现实元宇宙|VR设备购买|VR设备零售店

VR&#xff08;Virtual Reality&#xff0c;虚拟现实&#xff09;元宇宙是指基于虚拟现实技术构建的一个虚拟世界&#xff0c;这个世界可以模拟现实世界或者超出现实世界的一切事物和活动。在这个虚拟世界里&#xff0c;用户可以通过虚拟现实设备&#xff08;如头戴式显示器、手…