• 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的方法,里面有多个方法可以读取里面的值。

  • 相关阅读:
    好还是坏:人工智能二分类问题
    神经网络手写数字识别
    TensorFlow or PyTorch
    什么是深度学习
    五个常见 AI 开发库
    AI——第四次工业革命
    NodeJs获取不到POST参数
    Android权限
    【nodejs学习】3.进程管理及异步编程
    每日一题
  • 原文地址:https://www.cnblogs.com/grimm/p/14031241.html
Copyright © 2020-2023  润新知