Java异常重试设计核心在于语义识别、边界控制与稳定性权衡:一要区分瞬时性异常(可重试)与逻辑/数据异常(禁重试);二需配置指数退避、熔断、异步化及幂等保障;三应选用Spring Retry或Resilience4j等成熟框架而非手写while循环。

一、先判断“能不能重试”——异常类型决定重试资格
不是所有异常都适合重试。盲目重试可能放大故障(比如重复扣款、发两条通知)。
-
适合重试的异常:远程调用超时(
SocketTimeoutException)、网络中断(ConnectException)、服务暂时不可用(HTTP 503)、数据库连接池耗尽(SQLException中的连接拒绝)——这些是**瞬时性、外部依赖型**错误。 -
禁止重试的异常:业务校验失败(
IllegalArgumentException)、空指针(NullPointerException)、数据不一致(DataIntegrityViolationException)、幂等校验失败——这些是**程序逻辑或数据问题**,重试只会重复失败。 - 谨慎重试的异常:HTTP 400/401/403 等客户端错误,需结合业务判断;比如 401 可能因 token 过期,先刷新 token 再重试,而不是无脑重试。
二、再设计“怎么重试”——策略比代码更重要
重试不是加个 for 循环就行,关键在策略配置:
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- 次数控制:通常 3 次为上限。第 1 次失败后等待 100ms,第 2 次等待 300ms,第 3 次等待 1s(指数退避)。避免雪崩式请求打垮下游。
- 熔断兜底:连续失败 N 次(如 5 分钟内失败 10 次),自动熔断一段时间(如 30 秒),直接返回降级结果,不再发起请求。
- 异步化重试:对非核心链路(如日志上报、消息补偿),失败后写入本地队列或 DB,由后台任务异步重试,不阻塞主流程。
- 幂等保障:重试前确认操作是否幂等;不幂等的操作(如支付)必须带唯一业务 ID,服务端做去重,否则重试 = 多次执行。
三、最后选“用什么实现”——框架选型体现工程素养
手写 while + sleep 是下策。优先使用成熟方案:
- @Retryable(Spring Retry):声明式简单,支持注解配置最大重试次数、退避策略、忽略/包含的异常类型。适合 Spring Boot 项目。
- Resilience4j Retry:轻量、函数式、无 Spring 依赖,支持运行时动态调整策略,适合微服务多语言环境。
- 自研重试模板(封装 RetryTemplate):当需要统一监控(记录重试次数、耗时、最终结果)、对接告警或链路追踪时,封装一层更可控。
- 避免静态代理或硬编码 while:侵入业务、无法复用、难维护、没监控,面试中提这个会被认为缺乏工程意识。

















