- 定义注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Retryable {
int maxAttempts() default 3; // 最大重试次数
Class<? extends Throwable>[] retryOn() default Exception.class; // 需要重试的异常类型
}
- 切面RetryAspect,用于拦截Retryable注解的方法并执行重试逻辑
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class RetryAspect {
private static final Logger LOGGER = LoggerFactory.getLogger(RetryAspect.class);
@Around("@annotation(retryable)")
public Object retry(ProceedingJoinPoint joinPoint, Retryable retryable) throws Throwable {
int maxAttempts = retryable.maxAttempts();
Class<? extends Throwable>[] retryOn = retryable.retryOn();
int attempts = 0;
do {
attempts++;
try {
return joinPoint.proceed();
} catch (Throwable e) {
boolean retry = false;
for (Class<? extends Throwable> exception : retryOn) {
if (exception.isInstance(e)) {
retry = true;
break;
}
}
if (!retry || attempts >= maxAttempts) {
throw e;
}
LOGGER.warn("Retry attempt {} for method {}", attempts, joinPoint.getSignature().toShortString());
}
} while (attempts < maxAttempts);
throw new IllegalStateException("Unreachable");
}
}
- 使用注解(注意异常)
@GetMapping("/test")
@Retryable(maxAttempts = 3, retryOn = {BizException.class})
public void authtest() {
try {
String res = HttpUtil.get("http://localhost:8080/test");
JSONObject jsonObject = JSONObject.parseObject(res);
//todo ....
} catch (Exception e) {
throw new BizException("请求未正常返回");
}
}
当然还有可以直接使用Spring-Retry去直接处理这个逻辑