SpringCloud网关组件gateway报Only one connection receive subscriber allowed错误问题解决

1.实现网关全局过滤器时候报Only one connection receive subscriber allowed错误

原因是拦截器拦截获取到request POST请求体里面的body数据只能被读取一次,处理完相关逻辑后,需要重新写回新构建request,传递给下一个过滤器,报错如下:

因此对于读取的POST请求,读取完后重新构建一个request并通过ServerWebExchange转发到下一个过滤器

获取post请求的body的代码

    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());
        });
        //获取request body
        return bodyRef.get();
    }

上述代码能拿到body的Json字符串,解析出来可以拿到具体的数据,处理完相关逻辑,要进行转发

先对字符串写到字节缓冲区代码如下

//先将字符串写到字节缓冲    
private DataBuffer stringBuffer(String value) {
        byte[] bytes = value.getBytes(StandardCharsets.UTF_8);

        NettyDataBufferFactory nettyDataBufferFactory = new NettyDataBufferFactory(ByteBufAllocator.DEFAULT);
        DataBuffer buffer = nettyDataBufferFactory.allocateBuffer(bytes.length);
        buffer.write(bytes);
        return buffer;
    }

将读取过的body字符串重新写到新构建request对象中去,代码如下

//构建新的request对象 ----stringBuffer方法是上面的代码
private ServerHttpRequest resRequest(String body, ServerHttpRequest request) {
        DataBuffer bodyDataBuffer = stringBuffer(body);
        Flux<DataBuffer> bodyFlux = Flux.just(bodyDataBuffer);

        request = new ServerHttpRequestDecorator(request) {
            @Override
            public Flux<DataBuffer> getBody() {
                return bodyFlux;
            }
        };
        return request;

    }

 最后通过ServerWebExchange转发到下一个过滤器,代码如下

    private Mono<Void> getVoidMono(ServerWebExchange exchange, GatewayFilterChain chain, ServerHttpRequest request, String body) {
        ServerHttpRequest httpRequest = this.resRequest(body, request);
        return chain.filter(exchange.mutate().request(httpRequest).build());
    }

至此,解决网关报 Only one connection receive subscriber allowed.问题

参考:https://blog.csdn.net/tianyaleixiaowu/article/details/83375246

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值