簡體   English   中英

在錯誤情況下從WebClient獲取響應正文的正確方法是什么?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM