You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Spring Core 7结合Spring Rabbit 4.0.x、Spring Retry 2.0.12实现多异常对应不同重试策略的方案咨询

Spring Core 7结合Spring Rabbit 4.0.x、Spring Retry 2.0.12实现多异常对应不同重试策略的方案咨询

你遇到的这个问题其实是Spring 7版本带来的API迁移变化导致的——Spring 7把原本属于spring-retry模块的核心重试接口(RetryPolicy)迁移到了spring-core包下,而Spring Rabbit 4.0.x已经同步适配了这个新的core包接口,这就导致了之前依赖spring-retry接口的代码和现在的需求出现了冲突。

直接适配Spring Core 7原生重试API的解决方案

最简单的方式是切换到Spring Core 7自带的重试策略实现,它们都在org.springframework.core.retry包下,和Spring Rabbit 4.0.x的要求完全匹配,代码结构和你之前的写法几乎一致,只是需要调整导入的包路径:

import org.springframework.core.retry.RetryPolicy;
import org.springframework.core.retry.policy.SimpleRetryPolicy;
import org.springframework.core.retry.policy.AlwaysRetryPolicy;
import org.springframework.core.retry.policy.ExceptionClassifierRetryPolicy;
import java.sql.SQLException;
import java.net.SocketException;
import java.util.Map;

// 构建针对不同异常的重试策略
final RetryPolicy sqlRetryPolicy = new SimpleRetryPolicy(3);
final RetryPolicy connectionRetryPolicy = new AlwaysRetryPolicy();

// 创建分类重试策略并绑定异常与策略的对应关系
ExceptionClassifierRetryPolicy classifierRetryPolicy = new ExceptionClassifierRetryPolicy();
classifierRetryPolicy.setPolicyMap(Map.of(
    SQLException.class, sqlRetryPolicy,
    SocketException.class, connectionRetryPolicy
));

return classifierRetryPolicy;

兼容原有spring-retry策略的适配方案

如果你有遗留的自定义spring-retry策略不想重写,可以通过一个适配器类,把spring-retry的RetryPolicy转换为spring-core的RetryPolicy

首先编写适配器:

import org.springframework.retry.RetryPolicy;
import org.springframework.core.retry.RetryPolicy;
import org.springframework.core.retry.RetryContext;

// 用别名区分两个同名接口(如果你的开发环境支持),或者直接用全限定类名转换
public class SpringRetryToCoreAdapter implements org.springframework.core.retry.RetryPolicy {
    private final org.springframework.retry.RetryPolicy delegate;

    public SpringRetryToCoreAdapter(org.springframework.retry.RetryPolicy delegate) {
        this.delegate = delegate;
    }

    @Override
    public boolean canRetry(RetryContext context) {
        // 注意上下文类型的转换
        return delegate.canRetry((org.springframework.retry.RetryContext) context);
    }

    @Override
    public RetryContext open(RetryContext parent) {
        return delegate.open((org.springframework.retry.RetryContext) parent);
    }

    @Override
    public void close(RetryContext context) {
        delegate.close((org.springframework.retry.RetryContext) context);
    }

    @Override
    public void registerThrowable(RetryContext context, Throwable throwable) {
        delegate.registerThrowable((org.springframework.retry.RetryContext) context, throwable);
    }
}

然后用适配器包装原有策略:

// 原有spring-retry的策略实现
final org.springframework.retry.policy.SimpleRetryPolicy retryWithMaxAttempts = new org.springframework.retry.policy.SimpleRetryPolicy(3);
final org.springframework.retry.policy.AlwaysRetryPolicy connectionRetryPolicy = new org.springframework.retry.policy.AlwaysRetryPolicy();

// 转换为spring-core兼容的策略
org.springframework.core.retry.RetryPolicy sqlRetryPolicy = new SpringRetryToCoreAdapter(retryWithMaxAttempts);
org.springframework.core.retry.RetryPolicy connRetryPolicy = new SpringRetryToCoreAdapter(connectionRetryPolicy);

// 用core的分类策略组装
org.springframework.core.retry.policy.ExceptionClassifierRetryPolicy classifierRetryPolicy = new org.springframework.core.retry.policy.ExceptionClassifierRetryPolicy();
classifierRetryPolicy.setPolicyMap(Map.of(
    SQLException.class, sqlRetryPolicy,
    SocketException.class, connRetryPolicy
));

return classifierRetryPolicy;

问题根源总结

Spring 7对重试模块做了架构调整,将核心API整合到spring-core中,目的是减少模块依赖、统一重试逻辑的标准。Spring Rabbit 4.0.x作为适配Spring 7的版本,自然切换到了新的core接口,这就导致了旧代码中spring-retry接口和新接口的冲突。只要切换到新的包路径或者通过适配器兼容,就能解决这个问题。

备注:内容来源于stack exchange,提问作者nagaraj gond

火山引擎 最新活动