如何在 Spring 5.3 WebFlux 中获取 ClientResponse 主体作为 DataBuffer?

How to get ClientResponse body as DataBuffer in Spring 5.3 WebFlux?

在弃用 WebClient.exchange 方法之前,我曾将 ClientResponse 主体作为 Flux<DataBuffer> 获取并对其进行操作。

在 Spring 5.3 中,exchange() 方法已弃用,我想按照建议更改实现:

@deprecated since 5.3 due to the possibility to leak memory and/or connections; please, use {@link #exchangeToMono(Function)}, {@link #exchangeToFlux(Function)}; consider also using {@link #retrieve()} ...

试图在传递给 exchangeToMono 的 lambda 中执行相同的调用,但 clientResponse.bodyToFlux(DataBuffer::class.java) 总是 return 空流;其他实验(即获取主体作为单弦)也无法帮助获取主体。

在 Spring 5.3 中获取 ClientResponse 正文的标准方法是什么?

我正在寻找低级主体表示:类似于“数据缓冲区”、“字节数组”或“输入流”;避免任何类型的 parsing/deserialisation.

之前 Spring 5.3:

webClient
    .method(GET)
    .uri("http://somewhere.com")
    .exchange()
    .flatMap { clientResponse ->
       val bodyRaw: Flux<DataBuffer> = clientResponse.bodyToFlux(DataBuffer::class.java) 
       // ^ body as expected
           
       // other operations
    }

Spring之后5.3

webClient
    .method(GET)
    .uri("http://somewhere.com")
    .exchangeToMono { clientResponse ->
       val bodyRaw: Flux<DataBuffer> = clientResponse.bodyToFlux(DataBuffer::class.java)
       // ^ always empty flux
           
       // other operations
    }

新的 exchangeToMonoexchangeToFlux 方法要求 body 在回调中解码。查看此 GitHub issue 了解详细信息。

看看你的例子,也许你可以使用 retrieve,这是更安全的选择,bodyToFlux

webClient
        .method(GET)
        .uri("http://somewhere.com")
        .retrieve()
        .bodyToFlux(DataBuffer.class)

toEntityFlux 如果您需要访问响应详细信息,例如 headers 和状态

webClient
        .method(GET)
        .uri("http://somewhere.com")
        .retrieve()
        .toEntityFlux(DataBuffer.class)

处理错误

选项 1. 使用 onErrorResume 并处理 WebClientResponseException

webClient
        .method(GET)
        .uri("http://somewhere.com")
        .retrieve()
        .bodyToFlux(DataBuffer.class)
        .onErrorResume(WebClientResponseException.class, ex -> {
            if (ex.getStatusCode().equals(HttpStatus.NOT_FOUND)) {
                // ignore 404 and return empty
                return Mono.empty();
            }

            return Mono.error(ex);
        });

选项 2。使用 onStatus 便捷方法获取响应。

webClient
        .method(GET)
        .uri("http://somewhere.com")
        .retrieve()
        .onStatus(status -> status.equals(HttpStatus.NOT_FOUND), res -> {
            // ignore 404 and return empty
            return Mono.empty();
        })
        .bodyToFlux(DataBuffer.class)

两种方法都可用于反序列化错误响应Getting the response body in error case with Spring WebClient