spring-webflux中Flux<DataBuffer> 转String
Spring WebFlux既支持像Tomcat,Jetty这样的的传统容器(前提是支持Servlet 3.1 Non-Blocking IO API),又支持像Netty,Undertow那样的异步容器。不管是何种容器,Spring WebFlux都会将其输入输出流适配成Flux<DataBuffer>格式,以便进行统一处理。
在使用SpringCloud-gateway时,在各个filter里,都有ServerWebExchange对象,exchange里面携带着用户的request,request里带着用户请求的数据。
如果是Get请求传的参数,我们可以直接通过下图红框这样的方式获取参数的值,但是post请求的值就取不到了。
post的值都封装在了 Flux<DataBuffer> 对象中,那么我们怎么将它转为可读的String呢?
@Component @Slf4j @AllArgsConstructor public class HttpPostBodyFilter implements GlobalFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { ServerHttpRequest request = exchange.getRequest(); String method = request.getMethodValue(); String contentType = request.getHeaders().getFirst("Content-Type"); if ("POST".equals(method) && contentType.startsWith("multipart/form-data")){ return DataBufferUtils.join(exchange.getRequest().getBody()) .flatMap(dataBuffer -> { byte[] bytes = new byte[dataBuffer.readableByteCount()]; dataBuffer.read(bytes); try { String bodyString = new String(bytes, "utf-8"); log.info(bodyString); exchange.getAttributes().put("POST_BODY",bodyString); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } DataBufferUtils.release(dataBuffer); Flux<DataBuffer> cachedFlux = Flux.defer(() -> { DataBuffer buffer = exchange.getResponse().bufferFactory() .wrap(bytes); return Mono.just(buffer); }); ServerHttpRequest mutatedRequest = new ServerHttpRequestDecorator( exchange.getRequest()) { @Override public Flux<DataBuffer> getBody() { return cachedFlux; } }; return chain.filter(exchange.mutate().request(mutatedRequest) .build()); }); } return chain.filter(exchange); } @Override public int getOrder() { return -200; } }
这里面就是一种方式,post传的参数如下
上面代码处理后的bodyString如下:
还有一些其他的方式,如
-
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
-
String bodyStr = bodyRef.get();
-
System.out.println(bodyStr);
大家可以去看一下DataBuffer的方法,里面有多个方法可以读取里面的值。
学习时的痛苦是暂时的 未学到的痛苦是终生的