使用 WebFlux 调用 Restful 服务的错​​误处理示例

Example of error handling calling Restful services with WebFlux

我正在寻找使用 WebFlux 进行错误处理的简单示例。我在网上看了很多东西,但找不到适合我想要的东西。

我是 运行 Spring Boot 2.45

我这样调用服务:

Mono<ResponseObject> mono = webClient.post()
   .uri(url.toString())
   .header("Authorization", authToken)
   .body(Mono.just(contract), contract.getClass())
   .retrieve()
   .bodyToMono(ResponseObject.class);

我的所有服务 return Json 反序列化为 ResposeObject,看起来像这样:

"success" : true,
"httpStatus": 200,
"messages" : [
   "Informational message or, if not 200, then error messages"
],
result: {
   "data": {}
}

data 只是作为服务调用结果的对象映射。 如果有错误,显然success是false.

当我最终执行 ResponseObject response = mono.block() 时,我希望每次都获得一个 ResponseObject,即使出现错误也是如此。我的服务 return 是一个 ResponseObject 即使它 return 的 http 状态为 400,但 WebFlux 似乎拦截了它并抛出异常。显然,甚至没有调用服务的地方也可能出现 400 和 500 错误。但我仍然想将收到的任何消息包装到 ResponseObject 中。如何消除所有异常并始终获得 ResponseObject returned?

更新 只是想澄清一下,该服务本身不是 Reactive Webflux 服务。它 不是 return 单声道。相反,它正在调用其他 Restful 服务,我想使用 Webflux 来做到这一点。所以我要做的是调用外部服务,然后该服务执行 block()。在大多数情况下,我会调用多个服务,然后执行 Mono.zip 并调用 block() 来等待所有服务。

这似乎是我想做的事情:,但仍然无法正常工作。不确定 exchange() 是什么

正确的处理方法是通过 .onErrorResume,它允许您在发生任何错误时使用函数订阅后备发布者。您可以查看生成的异常和 return 自定义回退响应。

你可以这样做:

Mono<ResponseObject> mono = webClient.post()
   .uri(url.toString())
   .header("Authorization", authToken)
   .bodyValue(contract)
   .exchangeToMono(response -> {
      if (response.statusCode().equals(HttpStatus.OK)) {
          return response.bodyToMono(ResponseObject.class);
      }
      else if (response.statusCode().is4xxClientError()) {
          return response.bodyToMono(ResponseObject.class);
      }
      else {
          Mono<WebClientResponseException> wcre = response.createException();
          // examine wcre and create custom ResponseObject

          ResponseObject customRO = new ResponseObject();
          customRO.setSuccess(false);
          customRO.setHttpStatus(response.rawStatusCode());
          // you can set more default properties in response here
          return Mono.just( customRO );
      }
   });

此外,您不应在 Java 代码中的任何地方使用 .block()。只需确保从您的 REST 控制器 return a Mono<ResponseObject> 即可。如果你想在 returning 到客户端之前检查响应,你可以在管道末尾的 .map() 处理程序中这样做(就在 .onErrorResume 处理程序之后)

   .map(response -> {
      // examine content of response

      // in the end just return it
      return response;
   });