很多朋友在使用SpringCloudGateway的时候可能都碰到过以下几个问题

SpringCloudGateway中如何读取Post请求体
    private BodyInserter getBodyInserter(ServerWebExchange exchange) {
ServerRequest serverRequest = new DefaultServerRequest(exchange);
Mono<String> modifiedBody = serverRequest.bodyToMono(String.class)
.flatMap(body -> {
//这里的body就是Post的请求体
});
BodyInserter bodyInserter = BodyInserters.fromPublisher(modifiedBody, String.class);
return bodyInserter;
}
SpringCloudGateway中Post请求参数只能读取一次

这是因为Gateway默认使用的是SpringWebflux,解决这个问题需要容重新构造一个request来替换原先的request

        HttpHeaders headers=new HttpHeaders();
CachedBodyOutputMessage outputMessage = new CachedBodyOutputMessage(exchange, headers);
ServerHttpRequestDecorator decorator = this.getServerHttpRequestDecorator(exchange,outputMessage);
ServerHttpRequestDecorator decorator = new ServerHttpRequestDecorator(
exchange.getRequest()) {
@Override
public Flux<DataBuffer> getBody() {
return outputMessage.getBody();
}
};

当ServerHttpRequestDecorator构建完成之后需要在拦截器中使用如下方法替换原先的request

                    return chain.filter(exchange.mutate().request(decorator).build());

SpringCloudGateway中如何读取后段服务的返回数据

与上方替换request的思路一致,替换response即可

private ServerHttpResponse getServerHttpResponse(ServerWebExchange exchange) {
ServerHttpResponse originalResponse = exchange.getResponse();
DataBufferFactory bufferFactory = originalResponse.bufferFactory();
ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(originalResponse) { @Override
public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) { Flux<DataBuffer> flux = null;
if (body instanceof Mono) {
Mono<? extends DataBuffer> mono = (Mono<? extends DataBuffer>) body;
body = mono.flux(); }
if (body instanceof Flux) {
flux = (Flux<DataBuffer>) body;
return super.writeWith(flux.buffer().map(dataBuffers -> {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
dataBuffers.forEach(i -> {
byte[] array = new byte[i.readableByteCount()];
i.read(array);
DataBufferUtils.release(i);
outputStream.write(array, 0, array.length);
});
String result = outputStream.toString();
try {
if (outputStream != null) {
outputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
log.info("后端返回数据:{}", result);
return bufferFactory.wrap(result.getBytes());
}));
} log.info("降级处理返回数据:{}" + body);
return super.writeWith(body);
} };
return decoratedResponse;
}

上方是获取新的response,获取到新的之后和之前的套路一样,这样操作:

                    return chain.filter(exchange.mutate().request(decorator).response(decoratedResponse).build());

可能有的同学会碰到即使按照我上述的方法重写了response但是也无法读取到返回数据,这个原因可能是因为拦截器的优先级配置有问题,只需要实现Ordered接口并且重写getOrder方法,然后设置优先级小于-1即可

@Override
public int getOrder() {
return -2;
}

原文地址

SpringCloud Gateway拦截器遇到的小坑汇总的更多相关文章

  1. SpringMVC拦截器-路径语法-略坑

    项目中遇到一种场景,登录拦截器需要拦截.html后缀等动态请求,但是发现语法不对头.    <mvc:interceptors>      <mvc:interceptor> ...

  2. SpringMVC4拦截器配置遇到的坑

    目的:对get请求添加token验证(若为post请求可通过RequestBodyAdvice实现). 情景:因为有api版本管理的需求,重写了WebMvcConfigurationSupport类的 ...

  3. iOS总结:项目中的各种小坑汇总

    一.字符串转JSON 在网络请求时,如果服务端返回的是字符串,那么就需要我们自己封装一个类,将请求下来的字符串转换成json对象,从而存入模型中. 注意: 字符串中如果含有一些特殊转意符(如\n.\t ...

  4. JavaScript中的各种小坑汇总

    1.Number()将部分非数字类型转换为0 强制转换为数值类型函数: parseFloat.parseInt 优点:对非数值类型统一返回NaN 缺点:会将一部分符合数值类型的字符串也识别为数值 pa ...

  5. C++小坑汇总

    std::vector::end, 是构想的下一个push_back位置,并不实际指向vector中任何元素. Returns an iterator referring to the past-th ...

  6. SpringCloud:学习Gateway网关拦截器的ServerWebExchange

    1.Gateway的拦截器 我们要在项目中实现一个拦截器,需要继承两个类:GlobalFilter, Ordered GlobalFilter:全局过滤拦截器,在gateway中已经有部分实现,具体参 ...

  7. 【手记】小心在where中使用NEWID()的大坑 【手记】解决启动SQL Server Management Studio 17时报Cannot find one of more components...的问题 【C#】组件分享:FormDragger窗体拖拽器 【手记】注意BinaryWriter写string的小坑——会在string前加上长度前缀length-prefixed

    [手记]小心在where中使用NEWID()的大坑 这个表达式: ABS(CHECKSUM(NEWID())) % 3 --把GUID弄成正整数,然后取模 是随机返回0.1.2这三个数,不可能返回其它 ...

  8. Go+gRPC-Gateway(V2) 微服务实战,小程序登录鉴权服务(五):鉴权 gRPC-Interceptor 拦截器实战

    拦截器(gRPC-Interceptor)类似于 Gin 中间件(Middleware),让你在真正调用 RPC 服务前,进行身份认证.参数校验.限流等通用操作. 系列 云原生 API 网关,gRPC ...

  9. SpringMvc拦截器小测试

    前言 俗话说做项目是让人成长最快的方案,最近小编写项目的时候遇到了一个小问题.小编在项目中所负责的后台系统,但是后台系统是通过系统的页面是通过ifame联动的,那么这时候问题就来了,后台所做的所有操作 ...

随机推荐

  1. 小知识:设置sqlplus默认vi编辑器的好处

    如果是客户生产环境,不允许修改任何环境类的配置,那发现sqlplus默认不是我们熟悉的vi,可以在SQL>下临时指定,方便操作: SQL> define_editor=vi SQL> ...

  2. 企业架构如何实施的简介(TOGAF深度好文)

    本文来自企业架构学院: BangEA:如何实施企业架构? IT不仅是开展业务的手段,而且正在迅速演变为业务,IT绩效会直接影响企业的盈利能力,但很多企业并没有适时或充分的让IT组织参与业务的规划和决策 ...

  3. js实现post方式的异步请求

    <%@ page contentType="text/html;charset=UTF-8" language="java" %><html& ...

  4. .netcore2.1 JS-SDK 从后台获取微信签名,实现自定义分享标题、描述、图片

    最近项目移动端需要实现微信自定义分享功能,包含分享自定义标题.描述等. 首先到公众号的后台,功能设置里面,添加将要被分享的域名,如图 后端签名算法实现 ,参考腾讯开发者文档https://mp.wei ...

  5. Angular中使用bootstrap样式

    Angular中使用bootstrap样式 Angular中引入bootstrap的方法   方法1:在Angular.json中的styles数组中添加bootstrap路径 如下所示: " ...

  6. Kotlin Parameter specified as non-null is null

    报错信息如下: java.lang.IllegalArgumentException: Parameter specified as non-null is null: method kotlin.j ...

  7. Servlet 使用介绍(1)

    说明 本篇介绍java web中比较重要的一个技术:servlet.servlet是一种对用户请求动态响应的一个技术,是java web的核心一环.对于一般服务性质的纯后台服务应用而言,或许整个应用是 ...

  8. tomcat修改进程名称

    1.window平台: 打开tomcat_home\bin\setclasspath.bat文件,找到set _RUNJAVA=”%JRE_HOME%\bin\java”这一行. 将该行注释掉 ,然后 ...

  9. Sublime Text 3如何关闭自动更新

    1.Preferences -> Settings-User 2.插入下面代码:"update_check": false 如果有其他的设置,用逗号隔开,然后保存 3.Pre ...

  10. LInux:服务的管理-systemctl

    使用systemctl管理服务 服务的启动与停止 服务的启动与停止 命令格式:systemctl 选项 服务名 选项说明: start:启动;stop:停止:restart:重启:status:服务状 ...