[英]Java Spring WebClient how to get atribute from body response and set to a given class?
[英]What's the correct way to get the response body from a WebClient in an error case?
我是WebClient
和反應式編程的新手。 我想從請求中獲取響應主體。 如果發生錯誤,則必須記錄http代碼,標頭和正文,但仍應返回正文。
經過大量的挖掘和谷歌搜索,我找到了兩種解決方案。 但是,兩者對我來說都顯得復雜。 有沒有更簡單的解決方案?
呆在Mono
我發現了以下解決方案:
public Mono<String> log(ProtocolLine protocolLine) {
return webClient.post()
.uri("/log")
.body(BodyInserters.fromObject(protocolLine))
.exchange()
.flatMap(clientResponse -> {
Mono<String> stringMono = clientResponse.bodyToMono(String.class);
CompletableFuture<String> stringCompleteFuture = new CompletableFuture<String>();
Mono<String> bodyCompletedMono = Mono.fromFuture(stringCompleteFuture);
if (clientResponse.statusCode().isError()) {
stringMono.subscribe(bodyString -> {
LOGGER.error("HttpStatusCode = {}", clientResponse.statusCode());
LOGGER.error("HttpHeaders = {}", clientResponse.headers().asHttpHeaders());
LOGGER.error("ResponseBody = {}", bodyString);
stringCompleteFuture.complete(bodyString);
});
}
return bodyCompletedMono;
});
}
基於Flux
,需要更少的代碼。 但是我想如果我知道只有一個結果,我就不應該使用Flux。
public Flux<String> log(ProtocolLine protocolLine) {
return webClient.post()
.uri("/log")
.body(BodyInserters.fromObject(protocolLine))
.exchange()
.flux()
.flatMap(clientResponse -> {
Flux<String> stringFlux = clientResponse.bodyToFlux(String.class).share();
if (clientResponse.statusCode().isError()) {
stringFlux.subscribe(bodyString -> {
LOGGER.error("HttpStatusCode = {}", clientResponse.statusCode());
LOGGER.error("HttpHeaders = {}", clientResponse.headers().asHttpHeaders());
LOGGER.error("ResponseBody = {}", bodyString);
});
}
return stringFlux;
});
}
兩種解決方案都是丑陋和錯誤的。 您幾乎永遠不應該在反應式管道的中間進行訂閱。 訂戶通常是主叫客戶端,而不是您自己的應用程序。
public Mono<String> log(ProtocolLine protocolLine) {
return webClient.post()
.uri("/log")
.body(BodyInserters.fromObject(protocolLine))
.exchange()
.flatMap(clientResponse -> clientResponse.bodyToMono(String.class)
.doOnSuccess(body -> {
if (clientResponse.statusCode().isError()) {
log.error("HttpStatusCode = {}", clientResponse.statusCode());
log.error("HttpHeaders = {}", clientResponse.headers().asHttpHeaders());
log.error("ResponseBody = {}", body);
}
}));
}
在這里,您可以看到思維方式。 我們始終采用clientResponse
並將其主體映射到字符串。 然后,當訂戶(我們的調用客戶端)使用此Mono
時,我們執行doOnSuccess
並檢查狀態代碼是否有錯誤,如果是這種情況,我們將進行記錄。
doOnSuccess
方法返回void,因此它不“消耗”單聲道或任何東西,它只是在此Mono
表示其“本身具有某些東西”時觸發某物,而當其“完成”以便發出提示時才觸發。
可以以相同的方式與Flux
一起使用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.