为了账号安全,请及时绑定邮箱和手机立即绑定

如何使用Springboot对WebFlux进行异常处理?

如何使用Springboot对WebFlux进行异常处理?

慕尼黑5688855 2023-08-09 17:16:56
我有 3 个微服务应用程序。我正在尝试使用反应包中的 webclient 进行 2 次异步调用,然后在收到响应时将它们组合起来。示例代码:(引用自 - 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 或其他信息?我努力了:将 .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))))添加异常处理程序 - 但我确实没有控制器,所以这似乎不起作用。@ExceptionHandler(WebClientException.class)    public Exception handlerWebClientException(WebClientException webClientException) {        return new Data4xxException("Testing", webClientException);    }添加了一个包含 ControllerAdvice 和 ExceptionHandler 的类@ControllerAdvicepublic class WebFluxExceptionHandler {    @ExceptionHandler(WebClientException.class)    public Exception handlerWebClientException(WebClientException webClientException) {        return new Data4xxException("Testing", webClientException);    }}但我没有看到它们打印在 spring-boot 日志中。Mono.zip.block() 方法只是返回 null 并且实际上不会抛出任何异常。如何让 zip 方法抛出异常而不返回 null ?
查看完整描述

3 回答

?
一只萌萌小番薯

TA贡献1795条经验 获得超7个赞

执行此操作的方法是按以下方式使用 onErrorMap:


Mono<Person> personMono = client.get()

.uri("/person/{id}", personId)

.retrieve()

.bodyToMono(Person.class)

.onErrorMap((Throwable error) -> error);

onErrorMap将使 Mono 在 Zip 阻塞时真正抛出错误,终止 zip 并让 spring 或任何其他您想要处理异常的类。


查看完整回答
反对 回复 2023-08-09
?
HUWWW

TA贡献1874条经验 获得超12个赞

你问的时候不是很清楚


“如何让 zip 方法抛出异常而不返回 null?”


在 WebFlux 中,您通常不会抛出异常,而是传播异常然后处理它们。为什么?因为我们正在处理数据流,如果抛出异常,流就会结束,客户端会断开连接,事件链也会停止。


我们仍然希望维护数据流并在数据流经时处理不良数据。


您可以使用该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 )

如果您想做更具体的事情,您必须用您希望如何处理错误来更新您的问题。


查看完整回答
反对 回复 2023-08-09
?
HUH函数

TA贡献1836条经验 获得超4个赞

每当收到状态码为 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))

查看完整回答
反对 回复 2023-08-09
  • 3 回答
  • 0 关注
  • 189 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信