webflux编程

Spring WebFlux 多次读取 DataBuffer 类型的请求内容
方法一:基于内存缓存 —— 构造新的 DataBuffer 对象

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
     
        final ServerHttpRequest request = exchange.getRequest(); 
        long contentLength = request.getHeaders().getContentLength();

        if (contentLength <= 0) {
     
            return chain.filter(exchange);
        }

        return DataBufferUtils.join(request.getBody()).map(dataBuffer -> {
     
            exchange.getAttributes().put("cachedRequestBody", dataBuffer);

            ServerHttpRequest decorator = new ServerHttpRequestDecorator(request) {
     
                @Override
                public Flux<DataBuffer> getBody() {
     
                    return Mono.<DataBuffer>fromSupplier(() -> {
     
                        if (exchange.getAttributeOrDefault("cachedRequestBody", null) == null) {
     
                            // probably == downstream closed
                            return null;
                        }

                        // reset position
                        dataBuffer.readPosition(0);

                        // deal with Netty
                        NettyDataBuffer pdb = (NettyDataBuffer) dataBuffer;
                        return pdb.factory().wrap(pdb.getNativeBuffer().retainedSlice());
                    }).flux();
                }
            };

            // TODO 消费 dataBuffer,例如计算 dataBuffer 的哈希值并验证
            // ...

            return decorator

        })
        .switchIfEmpty(Mono.just(request))
        .flatMap(req -> chain.filter(exchange.mutate().request(req).build()))
        .doFinally(s -> {
     
            DataBuffer dataBuffer = exchange.getAttributeOrDefault("cachedRequestBody", null);
            if (dataBuffer != null) {
     
                DataBufferUtils.release(dataBuffer);
            }
        });
    }

方法二:基于内存缓存 —— byte[]

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
     
        final ServerHttpRequest request = exchange.getRequest(); 
        long contentLength = request.getHeaders().getContentLength();

        if (contentLength <= 0) {
     
            return chain.filter(exchange);
        }

        final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

        return Mono.create(sink -> {
     
             DataBufferUtils.write(request.getBody(), outputStream).subscribe(DataBufferUtils::release, sink::error, sink::success);
        })
        .then(Mono.just(request))
        .flatMap(req -> {
     
            log.debug("缓存大小:{}", outputStream.size());
            final ServerHttpRequestDecorator decorator = new ServerHttpRequestDecorator(req) {
     
                @Override
                public Flux<DataBuffer> getBody() {
     
                    return DataBufferUtils.read(new ByteArrayResource(outputStream.toByteArray()), exchange.getResponse().bufferFactory(), 1024 * 8);
                }
            };

            // TODO 对缓存的 ByteArrayOutputStream 进行处理,例如计算 ByteArrayOutputStream 中 byte[] 的哈希值并验证
            // ...

            return chain.filter(exchange.mutate().request(decorator).build());
        });
    }

方法三:基于文件缓存 —— Path

  @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
     
        final ServerHttpRequest request = exchange.getRequest(); 
        long contentLength = request.getHeaders().getContentLength();

        if (contentLength <= 0) {
     
            return chain.filter(exchange);
        }

        try {
     
            final Path tempFile = Files.createTempFile("HttpRequest", ".bin");

            return DataBufferUtils.write(request.getBody(), tempFile)
                .then(Mono.just(request))
                .flatMap(req -> {
     
                    final ServerHttpRequestDecorator decorator = new ServerHttpRequestDecorator(req) {
     
                        @Override
                        public Flux<DataBuffer> getBody() {
     
                            return DataBufferUtils.read(tempFile, exchange.getResponse().bufferFactory(), 1024 * 8, StandardOpenOption.READ);
                        }
                    };

                    // TODO 对缓存的 tempFile 进行处理,例如计算 tempFile 的哈希值并验证
                    // ...

                    return chain.filter(exchange.mutate().request(decorator).build());
                })
                .doFinally(s -> {
     
                    try {
     
                        Files.deleteIfExists(tempFile);
                    } catch (IOException e) {
     
                        throw new IllegalStateException(e);
                    }
                });

        } catch (IOException e) {
     
            throw new IllegalStateException(e);
        }
    }

注:

在请求 body 比较大的情况的测试中,发现调用 DataBufferUtils#join() 方法(方法一)会占用较大的内存,并且请求完毕时可能不会立刻释放,在下一次 GC 时可释放。调用 DataBufferUtils#write() 方法直接写到 OutputStream (方法二)或者临时文件(方法三)时,则不会占用过多内存。

webflux实战增删查改=====视频讲解的是非常好的。

实例文章:写的很好
https://segmentfault.com/q/1010000018526503
webflux编程_第1张图片
接受json数据还是按照mvc那一套就好了
返回json可以返回对象。
但是对于这种mono的处理方式还有待研究

restfor风格的传参
webflux编程_第2张图片
数据量很大,建议使用json参数

Mono file.flatMap(s -> {
Flux content = s.content();
// return content;
// 因为它的类型是flux,然而 Mono file.flatMap()的返回类型是mono,
// 所以会报如下错误: no instance(s) of type variable(s) R exist so that flux conforms to mono
// 不存在类型变量R的实例,以至于flux不符合mono<?extends R> 就是当前你返回的值的类型和该函数要求的值的返回类型不兼容
return null;
});


 AtomicInteger a= new AtomicInteger();
      Mono<FilePart> file.flatMap(s -> {
     
            Flux<DataBuffer> content = s.content();
            content.flatMap(aa->{
     
                InputStream inputStream = aa.asInputStream();
                System.out.println("hahhaha"); 
                a.set(10);
                  return null;
            });
            return null;
        });
        System.out.println(a.get()+"==============");  //打印结果为0

System.out.println(“hahhaha”);
a.set(10);

  • 这两条语句虽然执行了,但是不会产生任何作用:即不会改变a的值,也不会输出“haha”,因为他们是流里面的中间操作,除非你返回结果,流会将计算结果存入返回值。否则将会丢弃一切计算。

你可能感兴趣的:(工作总结)