最近在做网关改造,想要通过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. openstack 搭建

    #所有节点修改ip,主机名和hosts解析 controller 10.0.0.11 controller compute1 10.0.0.31 compute1 #所有节点准备本地repo源 rm ...

  2. Gradle之FTP文件下载

    Gradle之FTP文件下载 1.背景 项目上需要使用本地web,所以我们直接将web直接放入assets资源文件夹下.但是随着开发进行web包越来越大:所以我们想着从版本库里面去掉web将其忽略掉, ...

  3. ABP入门教程2 - 体系架构

    点这里进入ABP入门教程目录 介绍 应用程序代码库的分层是一种广泛接受的技术,可帮助降低复杂性并提高代码可重用性.为了实现分层体系结构,ASP.NET Boilerplate遵循域驱动设计的原理. D ...

  4. 修改robotframework的元素定位方式,使之支持带括号的xpath定位方式

    今天困扰我的一个问题终于解决了 robot框架默认的xpth定位方式是不支持带括号运算的xpth表达式的,例如: (//*[@content-desc="iv_message_icon_21 ...

  5. python中可变与不可变类型的全局变量

    python中的不可变类型的全局变量如int  a=1,str  b='hello', 若需要修改必须加global申明, 而全局变量是可变类型的,如list, dict ,则直接修改list.app ...

  6. IT人的立功,立言,立德三不朽

    最近几个月很忙,忙着当奶爸,忙着做加班狗,忙着补裤裆学技术……以至于快忘了要思考人生了! 古人立志穷极一生追求“立德”,“立功”,“立言”,以求不朽,为万世所景仰,为后人所传颂,实现人生的意义.立德者 ...

  7. Codeforces Round #603 (Div. 2) A. Sweet Problem 水题

    A. Sweet Problem the first pile contains only red candies and there are r candies in it, the second ...

  8. 适合新手:从零开发一个IM服务端(基于Netty,有完整源码)

    本文由“yuanrw”分享,博客:juejin.im/user/5cefab8451882510eb758606,收录时内容有改动和修订. 0.引言 站长提示:本文适合IM新手阅读,但最好有一定的网络 ...

  9. 学习 正则表达式 js java c# python 通用

    正则表达式 js java c# python 学习网站 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Globa ...

  10. netty ByteBuf与String相互转换

    String转为ByteBuf 1)使用String.getBytes(Charset),将String转为byte[]类型 2)使用Unpooled.wrappedBuffer(byte[]),将b ...