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