簡體   English   中英

如何使用 Springboot 對 WebFlux 進行異常處理?

[英]How to do Exception Handling for WebFlux using Springboot?

我有 3 個微服務應用程序。 我正在嘗試使用來自反應性 package 的 webclient 進行 2 get call async,然后在收到響應時將它們組合起來。

示例代碼:(參考 - https://docs.spring.io/spring/docs/5.1.9.RELEASE/spring-framework-reference/web-reactive.html#webflux-client-synchronous

Mono<Person> personMono = client.get().uri("/person/{id}", personId)
        .retrieve().bodyToMono(Person.class);

Mono<List<Hobby>> hobbiesMono = client.get().uri("/person/{id}/hobbies", personId)
        .retrieve().bodyToFlux(Hobby.class).collectList();

Map<String, Object> data = Mono.zip(personMono, hobbiesMono, (person, hobbies) -> {
            Map<String, String> map = new LinkedHashMap<>();
            map.put("person", personName);
            map.put("hobbies", hobbies);
            return map;
        })
        .block();

我的問題是如何向 get 調用添加異常處理?

如何檢查我是否得到了 404 或 204 或其他內容?

我努力了:

  1. 將.onStatus() 添加到 GET 調用
    .onStatus(HttpStatus::is4xxClientError, clientResponse ->
             Mono.error(new Data4xxException(String.format(
                "Could not GET data with id: %s from another app, due to error: 
                 %s", key, clientResponse))))
    .onStatus(HttpStatus::is5xxServerError, clientResponse ->
          Mono.error(new Data5xxException(
              String.format("For Data %s, Error Occurred: %s", key, clientResponse))))
  1. 添加異常處理程序 - 但我完全沒有 controller 所以這似乎不起作用。
@ExceptionHandler(WebClientException.class)
    public Exception handlerWebClientException(WebClientException webClientException) {
        return new Data4xxException("Testing", webClientException);
    }
  1. 添加了一個 class,其中包含 ControllerAdvice 和 ExceptionHandler
@ControllerAdvice
public class WebFluxExceptionHandler {

    @ExceptionHandler(WebClientException.class)
    public Exception handlerWebClientException(WebClientException webClientException) {
        return new Data4xxException("Testing", webClientException);
    }
}

但我沒有看到它們打印在 spring-boot 日志中。

Mono.zip.block() 方法只返回 null,實際上並沒有拋出任何異常。

如何讓 zip 方法拋出異常而不返回 null?

這樣做的方法是通過以下方式使用 onErrorMap:

Mono<Person> personMono = client.get()
.uri("/person/{id}", personId)
.retrieve()
.bodyToMono(Person.class)
.onErrorMap((Throwable error) -> error);

onErrorMap will make the Mono to actually throw an error when Zip blocks, terminating zip and letting spring or any other class that you want to handle the exception.

你問的時候不是很清楚

“如何讓 zip 方法拋出異常而不返回 null?”

在 webflux 中,您通常不會拋出異常,而是傳播異常然后處理它們。 為什么? 因為我們正在處理數據流,如果拋出異常,stream 結束,客戶端斷開連接,事件鏈停止。

我們仍然希望維護數據的 stream 並在壞數據流過時對其進行處理。

您可以使用doOnError方法處理錯誤。

.onStatus(HttpStatus::is4xxClientError, clientResponse ->
         Mono.error(new Data4xxException(String.format(
            "Could not GET data with id: %s from another app, due to error: 
             %s", key, clientResponse))))

Mono.zip( .. ).doOnError( //Handle your error, log or whatever )

如果您想做更具體的事情,您必須使用您希望如何處理錯誤來更新您的問題。

每當收到狀態碼為 4xx 或 5xx 的響應時,WebClient 中的 retrieve() 方法就會引發 WebClientResponseException。

與retrieve() 方法不同,exchange() 方法在4xx 或5xx 響應的情況下不會拋出異常。 您需要自己檢查狀態代碼並以您想要的方式處理它們。

   Mono<Object> result = webClient.get().uri(URL).exchange().log().flatMap(entity -> {
        HttpStatus statusCode = entity.statusCode();
        if (statusCode.is4xxClientError() || statusCode.is5xxServerError())
        {
            return Mono.error(new Exception(statusCode.toString()));
        }
        return Mono.just(entity);
    }).flatMap(clientResponse -> clientResponse.bodyToMono(JSONObject.class))

參考: https://www.callicoder.com/spring-5-reactive-webclient-webtestclient-examples/

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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