Resilience4j重试器仅对指定运行时异常重试,需确保自定义异常继承RuntimeException、在retryExceptions中明确配置该异常类,且调用链中不改变其原始类型。

Resilience4j 的重试器默认只对 RuntimeException 和 Error 重试,不重试受检异常(checked exceptions)。若你想让重试器**仅对某个自定义异常(比如 ServiceUnavailableException)重试**,关键在于正确配置 retryExceptions,并确保该异常是运行时异常或显式声明为重试目标。
确保自定义异常继承 RuntimeException
Resilience4j 默认不重试受检异常。如果你的自定义异常是 Exception 的子类(即受检异常),它不会被自动重试,即使你把它加进 retryExceptions。所以第一步是让异常本身是运行时异常:
让自定义异常继承 RuntimeException:
public class ServiceUnavailableException extends RuntimeException {
public ServiceUnavailableException(String message) {
super(message);
}
}
在 RetryConfig 中明确指定 retryExceptions
使用 RetryConfig.custom() 构建配置,并调用 retryExceptions(...) 列出你希望触发重试的异常类型(支持子类匹配):
立即学习“Java免费学习笔记(深入)”;
- 只传入你真正想重试的异常类,不要包含
Exception或Throwable,否则会扩大范围 - 多个异常可用 varargs 传入:
retryExceptions(A.class, B.class) - 注意:父类异常(如
RuntimeException)如果被加入,会导致所有运行时异常都被重试,违背“仅特定异常”的初衷
示例配置:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
RetryConfig config = RetryConfig.custom()
.maxAttempts(3)
.waitDuration(Duration.ofSeconds(1))
.retryExceptions(ServiceUnavailableException.class) // ✅ 只重试这个异常
.build();
Retry retry = Retry.of("service-call", config);
验证异常是否被实际抛出且未被吞掉
即使配置正确,如果业务代码中把 ServiceUnavailableException 捕获后“静默处理”或转成其他异常(比如包装成 new RuntimeException(e)),原始类型信息就丢失了,重试器无法识别。
- 确保抛出的是原生的
ServiceUnavailableException实例(或其子类) - 避免在调用链中用
catch (Exception e) { throw new RuntimeException(e); }这类转换 —— 它会把异常类型变成RuntimeException,不再匹配你的retryExceptions - 可通过日志或断点确认实际抛出的异常
getClass()确实是ServiceUnavailableException
配合 Retry.decorateCheckedSupplier 使用时需注意
如果你用的是 decorateCheckedSupplier(用于处理受检异常),它内部会把受检异常包装为 ExecutionException。此时直接配 retryExceptions(ServiceUnavailableException.class) 是无效的。
解决方式有两种:
-
推荐:改用
decorateSupplier,并确保你的方法签名抛出的是RuntimeException子类(即前面说的继承RuntimeException) - 或手动解包:通过
retryExceptions(ExecutionException.class)+ 自定义retryPredicate判断 cause 是否为ServiceUnavailableException
后者写法示例:
RetryConfig config = RetryConfig.custom()
.maxAttempts(3)
.retryOnException(throwable ->
throwable instanceof ExecutionException &&
throwable.getCause() instanceof ServiceUnavailableException)
.build();
不复杂但容易忽略:核心就是三点——异常得是运行时类型、配置里只列它、调用时别丢掉它的身份。

















