在弃用
WebClient.exchange
方法之前,我曾经将 ClientResponse 主体作为 Flux<DataBuffer>
并对其进行操作。
在 Spring 5.3 中,
exchange()
方法已被弃用,我想按照建议更改实现:
@deprecated since 5.3 due to the possibility to leak memory and/or 连接;请, 使用{@link #exchangeToMono(Function)},{@link #exchangeToFlux(Function)}; 也考虑使用 {@link #retrieve()} ...
试图在传递给
exchangeToMono
的lambda中做同样的调用,但是clientResponse.bodyToFlux(DataBuffer::class.java)
总是返回一个空的通量;其他实验(即让身体成为单弦)也无济于事。
在 Spring 5.3 中获取 ClientResponse 主体的标准方法是什么?
我正在寻找一个低级的主体表示:比如“数据缓冲区”、“字节数组”或“输入流”;避免任何类型的解析/反序列化。
春节前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
}
春后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
}
新的
exchangeToMono
和 exchangeToFlux
方法期望主体在回调中被解码。查看此GitHub问题了解详情。
看你的例子,也许你可以使用
retrieve
,这是更安全的选择,用bodyToFlux
webClient
.method(GET)
.uri("http://somewhere.com")
.retrieve()
.bodyToFlux(DataBuffer.class)
或
toEntityFlux
如果您需要访问标题和状态等响应详细信息
webClient
.method(GET)
.uri("http://somewhere.com")
.retrieve()
.toEntityFlux(DataBuffer.class)
处理错误
Option 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);
});
Option 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)
两种方法都可用于反序列化错误响应使用 Spring WebClient 在错误情况下获取响应主体
你可以使用
.retrieve()
.toEntityFlux(DataBuffer.class)
.map(...)
当然在这个解决方案中,首先一个 ResponseEntity 是由 spring 创建的,他们将它映射到另一个,但我没有找到更好的解决方案。