猿问

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

我有 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 的类

@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 ?


慕尼黑5688855
浏览 190回答 3
3回答

一只萌萌小番薯

执行此操作的方法是按以下方式使用 onErrorMap:Mono<Person> personMono = client.get().uri("/person/{id}", personId).retrieve().bodyToMono(Person.class).onErrorMap((Throwable error) -> error);onErrorMap将使 Mono 在 Zip 阻塞时真正抛出错误,终止 zip 并让 spring 或任何其他您想要处理异常的类。

HUWWW

你问的时候不是很清楚“如何让 zip 方法抛出异常而不返回 null?”在 WebFlux 中,您通常不会抛出异常,而是传播异常然后处理它们。为什么?因为我们正在处理数据流,如果抛出异常,流就会结束,客户端会断开连接,事件链也会停止。我们仍然希望维护数据流并在数据流经时处理不良数据。您可以使用该doOnError方法处理错误。.onStatus(HttpStatus::is4xxClientError, clientResponse ->&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Mono.error(new Data4xxException(String.format(&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "Could not GET data with id: %s from another app, due to error:&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;%s", key, clientResponse))))Mono.zip( .. ).doOnError( //Handle your error, log or whatever )如果您想做更具体的事情,您必须用您希望如何处理错误来更新您的问题。

HUH函数

每当收到状态码为 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))
随时随地看视频慕课网APP

相关分类

Java
我要回答