[Java]RetryTemplate重试机制工具
基于 RetryTemplate,封装为工具包使用
- RetryUtils
package com.common.utils;
import com.common.enums.RetryTypeEnum;
import lombok.SneakyThrows;
import org.springframework.retry.RecoveryCallback;
import org.springframework.retry.RetryCallback;
import org.springframework.retry.RetryState;
import org.springframework.retry.backoff.BackOffPolicy;
import org.springframework.retry.backoff.ExponentialBackOffPolicy;
import org.springframework.retry.backoff.ExponentialRandomBackOffPolicy;
import org.springframework.retry.backoff.FixedBackOffPolicy;
import org.springframework.retry.policy.SimpleRetryPolicy;
import org.springframework.retry.support.RetryTemplate;
/**
* @Author: jinyiming
* @Date: 2022/4/27
**/
public final class RetryUtils {
private RetryUtils() {
}
/**
* 重试最大等待时间
*/
private static final long MAX_RETRY_TIME = 60 * 1000L;
/**
* 使用策略进行重试
*
* @param retryCount 重试次数
* @param typeEnum {@link RetryTypeEnum} 重试类型
* @param millisecond 重试间隔时间
* @param retryCallback {@link RetryCallback} 需要重试的内容
* @param <T> 回调返回的对象类型
* @param <E> 它声明的异常类型可以被抛出
* @return T重试值
*/
public static <T, E extends Throwable> T retry(Integer retryCount, RetryTypeEnum typeEnum, long millisecond, RetryCallback<T, E> retryCallback) {
return retryCore(retryCount, typeEnum, millisecond, retryCallback, null, null);
}
/**
* 使用策略进行重试
*
* @param retryCount 重试次数
* @param typeEnum {@link RetryTypeEnum} 重试类型
* @param millisecond 重试间隔时间
* @param retryCallback {@link RetryCallback} 需要重试的内容
* @param recoveryCallback {@link RecoveryCallback} 重试完成之后还失败需要执行的内容
* @param <T> 回调返回的对象类型
* @param <E> 它声明的异常类型可以被抛出
* @return T重试值
*/
public static <T, E extends Throwable> T retry(Integer retryCount, RetryTypeEnum typeEnum, long millisecond, RetryCallback<T, E> retryCallback,
RecoveryCallback<T> recoveryCallback) {
return retryCore(retryCount, typeEnum, millisecond, retryCallback, recoveryCallback, null);
}
/**
* 使用策略进行重试
*
* @param retryCount 重试次数
* @param typeEnum {@link RetryTypeEnum} 重试类型
* @param millisecond 重试间隔时间
* @param retryCallback {@link RetryCallback} 需要重试的内容
* @param state {@link RetryState} 重试状态
* @param <T> 回调返回的对象类型
* @param <E> 它声明的异常类型可以被抛出
* @return T重试值
*/
public static <T, E extends Throwable> T retry(Integer retryCount, RetryTypeEnum typeEnum, long millisecond, RetryCallback<T, E> retryCallback,
RetryState state) {
return retryCore(retryCount, typeEnum, millisecond, retryCallback, null, state);
}
/**
* 使用策略进行重试
*
* @param retryCount 重试次数
* @param typeEnum {@link RetryTypeEnum} 重试类型
* @param millisecond 重试间隔时间
* @param retryCallback {@link RetryCallback} 需要重试的内容
* @param recoveryCallback {@link RecoveryCallback} 重试完成之后还失败需要执行的内容
* @param state {@link RetryState} 重试状态
* @param <T> 回调返回的对象类型
* @param <E> 它声明的异常类型可以被抛出
* @return T重试值
*/
public static <T, E extends Throwable> T retry(Integer retryCount, RetryTypeEnum typeEnum, long millisecond, RetryCallback<T, E> retryCallback,
RecoveryCallback<T> recoveryCallback, RetryState state) {
return retryCore(retryCount, typeEnum, millisecond, retryCallback, recoveryCallback, state);
}
@SneakyThrows
private static <T, E extends Throwable> T retryCore(Integer retryCount, RetryTypeEnum typeEnum, long millisecond, RetryCallback<T, E> retryCallback,
RecoveryCallback<T> recoveryCallback, RetryState state) {
SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy(retryCount > 0 ? retryCount : 3);
RetryTemplate retryTemplate = new RetryTemplate();
retryTemplate.setRetryPolicy(retryPolicy);
BackOffPolicy backOffPolicy;
switch (typeEnum) {
case EXPONENTIAL:
backOffPolicy = new ExponentialRandomBackOffPolicy();
((ExponentialRandomBackOffPolicy) backOffPolicy).setInitialInterval(millisecond);
((ExponentialRandomBackOffPolicy) backOffPolicy).setMaxInterval(MAX_RETRY_TIME);
break;
case RANDOM_EXPONENTIAL:
backOffPolicy = new ExponentialBackOffPolicy();
((ExponentialBackOffPolicy) backOffPolicy).setInitialInterval(millisecond);
((ExponentialBackOffPolicy) backOffPolicy).setMaxInterval(MAX_RETRY_TIME);
break;
default:
backOffPolicy = new FixedBackOffPolicy();
((FixedBackOffPolicy) backOffPolicy).setBackOffPeriod(millisecond);
break;
}
retryTemplate.setBackOffPolicy(backOffPolicy);
return retryTemplate.execute(retryCallback, recoveryCallback, state);
}
}
- RetryTypeEnum
package com.bf.form.common.enums;
/**
* @Author: jinyiming
* @Date: 2022/4/27
**/
public enum RetryTypeEnum implements ContentEnum {
/**
* 默认
*/
DEFAULT("默认", 1),
/**
* 指数
*/
EXPONENTIAL("指数", 2),
/**
* 随机指数
*/
RANDOM_EXPONENTIAL("随机指数", 3),
;
private final String content;
private final Integer value;
RetryTypeEnum(String content, Integer value) {
this.content = content;
this.value = value;
}
@Override
public String getContent() {
return this.content;
}
@Override
public Integer getValue() {
return this.value;
}
}
- 使用
BillInfo billInfo = RetryUtils.retry(5, RetryTypeEnum.EXPONENTIAL, 5000, (RetryCallback<BillInfo, Throwable>) context -> {
if (context.getRetryCount() >= 1) {
log.info(String.format("查询异常,正在重试%s次", context.getRetryCount()));
}
return billInfoDomain.getById();
}, context -> {
log.error(context.getLastThrowable().getMessage(), context.getLastThrowable());
throw context.getLastThrowable();
});
4.依赖包
org.springframework.retry