商城首页欢迎来到中国正版软件门户

您的位置:首页 >SpringBoot整合SpringRetry优雅实现接口重试的示例代码

SpringBoot整合SpringRetry优雅实现接口重试的示例代码

  发布于2026-07-30 阅读(0)

扫一扫,手机访问

接口调用失败时,直接返回错误往往不是最佳选择——有些场景下,重试一次就能解决问题。Spring Retry 提供了声明式重试机制,可以优雅地处理这类瞬态故障。

SpringBoot整合SpringRetry优雅实现接口重试的示例代码

一、引入依赖

话不多说,先上第一步:引入依赖。在 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

核心用法来了:@Retryable 注解。看一个支付退款的例子:当遇到 RemoteAccessExceptionTimeoutException 这类异常时,自动重试最多 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;
    }
}

从实际项目经验来看,重试机制是应对瞬态故障的利器,但也要注意不要滥用——比如对于幂等性要求不高的接口,重试可能带来重复操作。所以,结合业务场景,设计好重试次数、间隔和异常类型,才是优雅之道。

本文转载于:https://www.jb51.net/program/368307cct.htm 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注