Spring WebClient:指定异常重试后返回兜底值失败问题
问题原因
你的代码里,Retry.max(3)在重试3次耗尽后,会把原始的IllegalStateException包装成RetryExhaustedException抛出。而你用onErrorReturn(IllegalStateException.class, ...)只能匹配直接抛出的IllegalStateException,无法识别被包装后的异常,所以兜底值不会返回。
解决方案
有两种常用的修复方式:
方式一:让重试耗尽时抛出原始异常
在Retry配置里添加onRetryExhaustedThrow,指定重试耗尽后直接抛出原始异常,这样onErrorReturn就能正确匹配:
public Mono<String> getEmployee(String request) { return WebClient.create() .get() .uri("/accounts/" + request) .exchangeToMono(clientResponse -> { // 优化状态码判断,直接用枚举比较更清晰 if (clientResponse.statusCode().equals(HttpStatus.INTERNAL_SERVER_ERROR)) { return Mono.error(new IllegalStateException()); } if (clientResponse.statusCode().equals(HttpStatus.OK)) { return clientResponse.bodyToMono(String.class); } return Mono.error(new IllegalCallerException()); }) .retryWhen(Retry.max(3) .filter(throwable -> throwable instanceof IllegalStateException) // 关键配置:重试耗尽时抛出原始异常 .onRetryExhaustedThrow((spec, signal) -> signal.failure())) .onErrorReturn(IllegalStateException.class, "TECHNICAL_ERROR") .log(); }
方式二:匹配包装后的异常
如果不想修改Retry配置,可以让onErrorReturn判断异常链,匹配RetryExhaustedException且其原因是IllegalStateException:
public Mono<String> getEmployee(String request) { return WebClient.create() .get() .uri("/accounts/" + request) .exchangeToMono(clientResponse -> { if (clientResponse.statusCode().equals(HttpStatus.INTERNAL_SERVER_ERROR)) { return Mono.error(new IllegalStateException()); } if (clientResponse.statusCode().equals(HttpStatus.OK)) { return clientResponse.bodyToMono(String.class); } return Mono.error(new IllegalCallerException()); }) .retryWhen(Retry.max(3).filter(throwable -> throwable instanceof IllegalStateException)) // 匹配包装后的异常 .onErrorReturn(throwable -> throwable instanceof RetryExhaustedException && throwable.getCause() instanceof IllegalStateException, "TECHNICAL_ERROR") .log(); }
补充说明
第一种方式更直观,能保持异常类型的一致性;第二种方式不需要改动Retry逻辑,适合需要保留RetryExhaustedException上下文的场景。另外,建议在exchangeToMono里用Mono.error()抛出异常,而不是直接throw,因为Reactor中直接抛出 unchecked 异常虽然能被捕获,但用Mono.error()更符合响应式编程的规范。
内容的提问来源于stack exchange,提问作者nanpakal
相关产品推荐
相关产品推荐

