You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring RetryTemplate针对特定异常重试陷入无限循环问题求助

问题根源

你的ExceptionClassifierRetryPolicy每次触发异常分类时,都会新建一个SimpleRetryPolicy实例。由于新实例无法共享重试上下文(比如已重试次数),每次判断都会认为是第1次重试,永远达不到5次上限,最终导致无限循环。

解决方案

方案一:复用重试策略实例(修复原方案)

提前初始化SimpleRetryPolicy和NeverRetryPolicy实例,让分类器直接返回已创建的实例,这样重试次数会被正确累计:

private static RetryTemplate setupRetryTemplate() { 
    RetryTemplate template = new RetryTemplate();    
    // 退避策略保持不变
    FixedBackOffPolicy fixedBackOffPolicy = new FixedBackOffPolicy();
    fixedBackOffPolicy.setBackOffPeriod(300L);
    template.setBackOffPolicy(fixedBackOffPolicy);

    // 提前初始化重试策略实例,避免每次新建
    SimpleRetryPolicy dataAccessRetryPolicy = new SimpleRetryPolicy();
    dataAccessRetryPolicy.setMaxAttempts(5);
    NeverRetryPolicy neverRetryPolicy = new NeverRetryPolicy();

    ExceptionClassifierRetryPolicy retryPolicy = new ExceptionClassifierRetryPolicy();
    retryPolicy.setExceptionClassifier(exception -> {
        if (exception instanceof DataAccessResourceFailureException) {
            return dataAccessRetryPolicy; // 返回同一个实例,共享重试上下文
        } else {
            return neverRetryPolicy; // 返回同一个实例
        }
    });

    template.setRetryPolicy(retryPolicy);
    return template;
}

方案二:改用SimpleRetryPolicy直接配置(更简洁)

无需使用ExceptionClassifierRetryPolicy,直接通过SimpleRetryPolicy指定允许重试的异常类型和次数,逻辑更直观:

private static RetryTemplate setupRetryTemplate() { 
    RetryTemplate template = new RetryTemplate();    
    // 退避策略保持不变
    FixedBackOffPolicy fixedBackOffPolicy = new FixedBackOffPolicy();
    fixedBackOffPolicy.setBackOffPeriod(300L);
    template.setBackOffPolicy(fixedBackOffPolicy);

    // 配置仅对DataAccessResourceFailureException重试5次
    Map<Class<? extends Throwable>, Boolean> retryableExceptions = new HashMap<>();
    retryableExceptions.put(DataAccessResourceFailureException.class, true);
    
    SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy(
        5, // 最大重试次数
        retryableExceptions,
        true, // 是否重试该异常的子类(可选,按需调整)
        true  // 是否重试RuntimeException(可选)
    );

    template.setRetryPolicy(retryPolicy);
    return template;
}
额外优化建议

调用代码中,建议直接抛出原异常而非新建异常,保留完整堆栈信息便于调试:

catch (DataAccessResourceFailureException ex) {
    log.error("Exception DataAccessResourceFailureException :  {}", ex.getMessage(), ex);
    throw ex; // 直接抛出原异常,而非新建
}

内容的提问来源于stack exchange,提问作者Shail Panchal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 06:46:09