当前位置: 首页>大数据>正文

解决gateway中body只能取一次

1、自定义缓存存body

@Component
public class CacheBodyGatewayFilter implements Ordered, GlobalFilter {

    private static final String CACHE_REQUEST_BODY_OBJECT_KEY = "cachedRequestBodyObject";

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        if (exchange.getRequest().getHeaders().getContentType() == null) {
            return chain.filter(exchange);
        } else {
            return DataBufferUtils.join(exchange.getRequest().getBody())
                    .flatMap(dataBuffer -> {
                        DataBufferUtils.retain(dataBuffer);
                        Flux<DataBuffer> cachedFlux = Flux
                                .defer(() -> Flux.just(dataBuffer.slice(0, dataBuffer.readableByteCount())));
                        ServerHttpRequest mutatedRequest = new ServerHttpRequestDecorator(
                                exchange.getRequest()) {
                            @Override
                            public Flux<DataBuffer> getBody() {
                                return cachedFlux;
                            }

                        };
                        exchange.getAttributes().put(CACHE_REQUEST_BODY_OBJECT_KEY, cachedFlux);

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

    @Override
    public int getOrder() {
        return Ordered.HIGHEST_PRECEDENCE;
    }

取body的方式

 //获取request body
 Flux<DataBuffer> cachedBody = exchange.getAttribute(CACHE_REQUEST_BODY_OBJECT_KEY);
 if (cachedBody != null) {
       bodyStr = toRaw(cachedBody);
 }

 private static String toRaw(Flux<DataBuffer> body) {
        AtomicReference<String> rawRef = new AtomicReference<>();
        body.subscribe(buffer -> {
            byte[] bytes = new byte[buffer.readableByteCount()];
            buffer.read(bytes);
            DataBufferUtils.release(buffer);
            rawRef.set(Strings.fromUTF8ByteArray(bytes));
        });
        return rawRef.get();
    }

这种办法是可以用,但是会出现堆外内存泄漏的问题,可以参考这个改造,这个里面的方式很多,也讲到每种方式的问题。比较全面。

2、使用gateway已缓存的body

这种方式是上面里面没有讲到的方式,是阅读源码后找到的一种便捷途径,适用于全局的所有请求的body都需要使用,当然也可以根据你的需求,只对部分Routes做初始化。

3、gateway路由配置

这种方式和上面第二种基本方式一样,也是使用gateway已经实现的东西,这个更加好用,可以使用配置直接添加一个参数就可以。

https://www.cnblogs.com/mirakel/p/15222430.html
https://www.51cto.com/article/774780.html


https://www.xamrdz.com/bigdata/7u51994765.html

相关文章: