您的位置:首页 >SpringBoot整合SpringRetry优雅实现接口重试的示例代码
发布于2026-07-30 阅读(0)
扫一扫,手机访问
接口调用失败时,直接返回错误往往不是最佳选择——有些场景下,重试一次就能解决问题。Spring Retry 提供了声明式重试机制,可以优雅地处理这类瞬态故障。

话不多说,先上第一步:引入依赖。在 pom.xml 中加入 spring-retry 和 aspectjwea ver 这两个包。前者是重试机制的核心,后者提供 AOP 支持,以便实现声明式注解。
org.springframework.retry spring-retry org.aspectj aspectjwea ver
开启重试功能,其实很简单。在 Spring Boot 启动类上加上 @EnableRetry 注解,就相当于告诉 Spring:“嘿,我要用重试机制了,准备好 AOP 拦截。”
@SpringBootApplication
@EnableRetry
public class SeckillApplication {
public static void main(String[] args) {
SpringApplication.run(SeckillApplication.class, args);
}
}
核心用法来了:@Retryable 注解。看一个支付退款的例子:当遇到 RemoteAccessException 或 TimeoutException 这类异常时,自动重试最多 3 次,每次间隔 1 秒,并且每次重试间隔翻倍(2 秒、4 秒……)。这个注解里配置了哪些细节?
@Service
public class PaymentService {
private static final Logger log = LoggerFactory.getLogger(PaymentService.class);
@Retryable(
value = {RemoteAccessException.class, TimeoutException.class},
maxAttempts = 3,
backoff = @Backoff(delay = 1000, multiplier = 2)
)
public boolean refund(String orderNo) {
log.info("退款请求: {}", orderNo);
// 调用第三方支付接口
return thirdPartyRefund(orderNo);
}
@Recover
public boolean recover(RemoteAccessException e, String orderNo) {
log.error("退款失败,记录到异常表: {}", orderNo, e);
// 记录到失败表,人工处理
return false;
}
}
注意那个 @Recover 注解的方法——这是兜底回调。当所有重试都失败后,会执行这个方法,通常用来记录异常、发告警或写入人工处理队列。两者必须参数匹配,才能正确关联。
如果注解方式还不够灵活,比如需要更复杂的重试间隔策略,可以用编程式配置一个 RetryTemplate Bean。比如下面这个配置,定义了指数退避策略:初始间隔 1 秒,每次翻倍,最大间隔 10 秒,最多重试 5 次。
@Configuration
public class RetryConfig {
@Bean
public RetryTemplate retryTemplate() {
RetryTemplate template = new RetryTemplate();
// 重试策略:最多重试5次,间隔递增
ExponentialBackOffPolicy backOff = new ExponentialBackOffPolicy();
backOff.setInitialInterval(1000);
backOff.setMultiplier(2);
backOff.setMaxInterval(10000);
template.setBackOffPolicy(backOff);
// 异常判断:哪些异常需要重试
SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();
retryPolicy.setMaxAttempts(5);
template.setRetryPolicy(retryPolicy);
return template;
}
}
有了自定义的 RetryTemplate,就可以在业务代码中直接调用了。这种方式适合那些需要动态控制重试逻辑的场景,比如根据订单状态决定是否重试。
@Service
public class OrderService {
@Autowired
private RetryTemplate retryTemplate;
public boolean processOrder(Long orderId) {
return retryTemplate.execute(context -> {
log.info("处理订单,第{}次尝试", context.getRetryCount() + 1);
return doProcess(orderId);
}, context -> {
log.error("最终失败", context.getLastThrowable());
return false;
});
}
}
execute 方法接收两个回调:第一个是重试执行体,第二个是重试耗尽后的兜底逻辑。注意 context 里可以拿到当前重试次数,方便记录日志。
如果你想全局统一控制重试次数,可以在 application.yml 里配置:
spring:
retry:
max-attempts: 3 # 全局最大重试次数
不过这个配置只对 RetryTemplate 默认行为有效,注解方式里自己指定的 maxAttempts 优先级更高。
最后来看一个经典场景:秒杀系统的库存扣减。通常使用乐观锁防止超卖,但乐观锁失败时(比如数据库行锁冲突),直接报错会影响用户体验。这时用重试机制,在 200 毫秒后自动重试,最多 3 次,就能有效提升成功率。
@Service
public class SeckillService {
@Retryable(
value = OptimisticLockException.class,
maxAttempts = 3,
backoff = @Backoff(delay = 200)
)
public boolean deductStock(Long productId) {
// 乐观锁失败时自动重试
return productMapper.updateStock(productId) > 0;
}
}
从实际项目经验来看,重试机制是应对瞬态故障的利器,但也要注意不要滥用——比如对于幂等性要求不高的接口,重试可能带来重复操作。所以,结合业务场景,设计好重试次数、间隔和异常类型,才是优雅之道。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8