最近在做网关改造,想要通过Gateway过滤器获取ResponseBody的值,查看了网上的帖子和官网内容:

帖子:https://cloud.tencent.com/developer/article/1384111

官网:https://github.com/spring-cloud/spring-cloud-gateway/blob/master/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/rewrite/ModifyResponseBodyGatewayFilterFactory.java

但在实际操作中却掉坑里了,居然不起作用,就是不进重写但writeWith方法

 @Component
@Order(-2)
public class EncryptResponseBodyFilter implements GlobalFilter { @Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpResponse originalResponse = exchange.getResponse();
DataBufferFactory bufferFactory = originalResponse.bufferFactory();
ServerHttpResponseDecorator response = new ServerHttpResponseDecorator(originalResponse) { @Override
public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
if (getStatusCode().equals(HttpStatus.OK) && body instanceof Flux) { Flux<? extends DataBuffer> fluxBody = Flux.from(body);
return super.writeWith(fluxBody.map(dataBuffer -> {
// probably should reuse buffers
byte[] content = new byte[dataBuffer.readableByteCount()];
dataBuffer.read(content);
//释放掉内存
DataBufferUtils.release(dataBuffer);
String s = new String(content, Charset.forName("UTF-8"));
//TODO,s就是response的值,想修改、查看就随意而为了
byte[] uppedContent = s.getBytes();
return bufferFactory.wrap(uppedContent);
}));
}
return super.writeWith(body);
} @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(response).build());
}

后来与帖子和官网代码内容对比,只有Order的方式不同,就换了下实现Ordered重写getOrder方法方式试试,结果出乎意料,居然好用了!!!

真的是绞尽脑汁啊,浪费了不少时间。。。。

后来发现响应数据存在分段响应的问题:

参考:https://blog.csdn.net/fayeyiwang/article/details/9137// JSON响应数据拼接容器

private static Joiner joiner = Joiner.on("");

@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpResponse originalResponse = exchange.getResponse();
DataBufferFactory bufferFactory = originalResponse.bufferFactory();
ServerHttpResponseDecorator response = new ServerHttpResponseDecorator(originalResponse) {
@Override
public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
if (getStatusCode().equals(HttpStatus.OK) && body instanceof Flux) {
// 获取ContentType,判断是否返回JSON格式数据
String originalResponseContentType = exchange.getAttribute(ORIGINAL_RESPONSE_CONTENT_TYPE_ATTR);
if(StringUtils.isNotBlank(originalResponseContentType) && originalResponseContentType.contains("application/json")) {
Flux<? extends DataBuffer> fluxBody = Flux.from(body);
return super.writeWith(fluxBody.buffer().map(dataBuffers -> {//解决返回体分段传输
List<String> list = Lists.newArrayList();
dataBuffers.forEach(dataBuffer -> {
try {
byte[] content = new byte[dataBuffer.readableByteCount()];
dataBuffer.read(content);
DataBufferUtils.release(dataBuffer); list.add(new String(content, "utf-8"));
} catch (Exception e) {
logger.info("动态加载API加密规则失败,失败原因:{}", Throwables.getStackTraceAsString(e));
}
});
String responseData = joiner.join(list);
// 二次处理(加密/过滤等)如果不需要做二次处理可直接跳过下行
responseData = beforeBodyWriteInternal(responseData, exchange.getRequest());
byte[] uppedContent = new String(responseData.getBytes(), Charset.forName("UTF-8")).getBytes();
originalResponse.getHeaders().setContentLength(uppedContent.length);
return bufferFactory.wrap(uppedContent);
}));
}
}
return super.writeWith(body);
} @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(response).build());
}

获取SpringCloud gateway响应的response的值,记录踩坑的更多相关文章

  1. Local Response Normalization作用——对局部神经元的活动创建竞争机制,使得其中响应比较大的值变得相对更大,并抑制其他反馈较小的神经元,增强了模型的泛化能力

    AlexNet将LeNet的思想发扬光大,把CNN的基本原理应用到了很深很宽的网络中.AlexNet主要使用到的新技术点如下. (1)成功使用ReLU作为CNN的激活函数,并验证其效果在较深的网络超过 ...

  2. 拦截器HandlerInterceptorAdapter的postHandle和afterCompletion无法获取response返回值问题

    缘起 有一个需求,在进入controller之前验证调用次数是否超过限制,在响应之后判断是否正常返回,对调用次数进行+1,发现带@RestController的类和带@ResponseBody的方法在 ...

  3. SpringCloud gateway (史上最全)

    疯狂创客圈 Java 分布式聊天室[ 亿级流量]实战系列之 -25[ 博客园 总入口 ] 前言 ### 前言 疯狂创客圈(笔者尼恩创建的高并发研习社群)Springcloud 高并发系列文章,将为大家 ...

  4. SpringCloud gateway 3

    参考博客:https://www.cnblogs.com/crazymakercircle/p/11704077.html 1.1 SpringCloud Gateway 简介 SpringCloud ...

  5. SpringCloud Gateway 测试问题解决

    本文针对于测试环境SpringCloud Gateway问题解决. 1.背景介绍 本文遇到的问题都是在测试环境真正遇到的问题,不一定试用于所有人,仅做一次记录,便于遇到同样问题的干掉这些问题. 使用版 ...

  6. SpringCloud请求响应数据转换(二)

    上篇文章记录了从后端接口返回数据经过切面和消息转换器处理后返回给前端的过程.接下来,记录从请求发出后到后端接口调用过的过程. web请求处理流程 源码分析 ApplicationFilterChain ...

  7. 万字长文:SpringCloud gateway入门学习&实践

    官方文档:https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/# ...

  8. SpringCloud Gateway微服务网关实战与源码分析-上

    概述 定义 Spring Cloud Gateway 官网地址 https://spring.io/projects/spring-cloud-gateway/ 最新版本3.1.3 Spring Cl ...

  9. 转:PHP--获取响应头(Response Header)方法

    转:http://blog.sina.com.cn/s/blog_5f54f0be0102uvxu.html PHP--获取响应头(Response Header)方法 方法一: ========== ...

随机推荐

  1. thinkphp 5.x No input file specified 解决

    原规则: <IfModule mod_rewrite.c> Options +FollowSymlinks -Multiviews RewriteEngine On RewriteCond ...

  2. Python 函數 Function

    函數最初被設計出來,是用來減輕重複 coding 一段相同的代碼,這之間只有代碼 (方法,Method) 的重用,但還沒有物件導向OO整個Object 的屬性與方法被封裝重用的概念. 函數的定義很簡單 ...

  3. Beyond Compare 4.X 破解方法(亲测有效)

    Windows下Beyond Compare 4 30天评估到期了的话,可以尝试下面两种方式: 破解方式把Beyond Compare 4安装文件夹下面的BCUnrar.dll文件删掉就行了,但是这种 ...

  4. SAP depreciation key config

    正常折旧 Configure 1.分配总帐科目 spro进入后台配置 –> Financial Accounting(New) –> Asset Accounting –> Depr ...

  5. 记录Android开发中遇到的坑

    1. 出现错误提示:Intel HAXM is required to run this AVD,VT-x is disabled in BIOS的解决办法. 点击SDK图标,安装Intel x86 ...

  6. linux学习(四)复制(cp)移动(mv)删除(rm)查找(find)文件、文件夹操作、软硬链接的区别

    目录 复制文件 mv命令 rm命令 touch 命令 file命令 find命令 grep命令 mkdir命令 rmdir命令 @(复制移动删除查找文件.软硬链接的区别) 复制文件 cp命令用于复制文 ...

  7. echarts js报错 Cannot read property 'getAttribute' of null

    本文将为您描述如何解决 eharts.js报错 Uncaught TypeError: Cannot read property 'getAttribute' of null 的问题 根据报错信息查找 ...

  8. SPA项目之CRUD+表单验证

    1. 表单验证 Form组件提供了表单验证的功能,只需要通过 rules 属性传入约定的验证规则, 并将Form-Item的prop属性设置为需校验的字段名即可 <el-dialog :titl ...

  9. RNN及其变体框架

    RNN及其变体框架  含RNN推导 LSTM理解 理解LSTM网络  算法细节理解及参考文献  

  10. [Vue专题] 对比vue-cli2.x和vue-cli3.x的搭建

    简介:深入了解脚手架vue-cli2.x版本与3.x版本构建项目的区别 搭建前提条件: node环境 node是傻瓜式安装的,直接去官网下载安装不断下一步 命令行输入node -v查询版本号,有版本号 ...