如何使用 ReadBodyPredicateFactory 缓存负载数据

sor*_*rab 1 cloud spring gateway

我有 Spring Boot 微服务,并使用 swagger 发送大量有效负载。在服务器上我只得到 15000 个字符,并且重置 2000 个字符未读取。

如何使用 ReadBodyPredicateFactory 缓存正文消息文本?

我正在使用 springcloudgateway 并添加了过滤器。在 apply 方法的过滤器中,我尝试使用读取有效负载 json

  DefaultServerRequest serverRequest = new DefaultServerRequest(exchange);
  body = serverRequest.bodyToMono(String.class).toFuture().get();
Run Code Online (Sandbox Code Playgroud)

有时会挂起。

我尝试使用 Flux,然后只收到一半消息 Flux body = request.getBody();

    body.subscribe(buffer -> {

        try {
            System.out.println("byte count:" + 
           buffer.readableByteCount());
            byte[] bytes = new byte[buffer.readableByteCount()];
            buffer.read(bytes);
            DataBufferUtils.release(buffer);
            String bodyString = new String(bytes, StandardCharsets.UTF_8);
            sb.append(bodyString);
        } catch (Exception e) {
            e.printStackTrace();
        }
Run Code Online (Sandbox Code Playgroud)

小智 6

最近,我的应用程序中需要类似的东西,我发现它可以通过 Spring Cloud Gateway 在ServerWebExchangeUtils中内置的缓存来实现

在某些业务案例中使用请求内容的过滤器之前,我创建了一个仅强制内容缓存的过滤器:

@Component
class CachingRequestBodyFilter extends AbstractGatewayFilterFactory<CachingRequestBodyFilter.Config> {

    public CachingRequestBodyFilter() {
        super(Config.class);
    }

    public GatewayFilter apply(final Config config) {
        return (exchange, chain) -> ServerWebExchangeUtils.cacheRequestBody(exchange,
            (serverHttpRequest) -> chain.filter(exchange.mutate().request(serverHttpRequest).build()));
    }

    public static class Config {
    }
}
Run Code Online (Sandbox Code Playgroud)

在任何后续过滤器中,我们都可以提取请求正文的内容,如下所示:

// some ReadRequestBodyFilter filter

public GatewayFilter apply(final Config config) {
    return (exchange, chain) -> {
        final var cachedBody = new StringBuilder();
        final var cachedBodyAttribute = exchange.getAttribute(CACHED_REQUEST_BODY_ATTR);
        if (!(cachedBodyAttribute instanceof DataBuffer)) {
            // caching gone wrong error handling
        }
        final var dataBuffer = (DataBuffer) cachedBodyAttribute;
        cachedBody.append(StandardCharsets.UTF_8.decode(dataBuffer.asByteBuffer()).toString());
        final var bodyAsJson = cachedBody.toString();

        // some processing

        return chain.filter(exchange);
    };
}
Run Code Online (Sandbox Code Playgroud)

那么网关配置将如下所示:

spring:
  cloud:
    gateway:
      routes:
        - [...]
          filters:
            - CachingRequestBodyFilter
            - ReadRequestBodyFilter
Run Code Online (Sandbox Code Playgroud)