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如下:

还有一些其他的方式,如

  1.  
    AtomicReference<String> bodyRef = new AtomicReference<>();
  2.  
    body.subscribe(buffer -> {
  3.  
    CharBuffer charBuffer = StandardCharsets.UTF_8.decode(buffer.asByteBuffer());
  4.  
    DataBufferUtils.release(buffer);
  5.  
    bodyRef.set(charBuffer.toString());
  6.  
    });
  7.  
    //获取request body
  8.  
    String bodyStr = bodyRef.get();
  9.  
    System.out.println(bodyStr);

大家可以去看一下DataBuffer的方法,里面有多个方法可以读取里面的值。

posted @ 2020-11-24 17:02  爱你爱自己  阅读(5582)  评论(0编辑  收藏  举报