Recentemente, uma empresa precisa de um mecanismo de repetição e sinto que devo escrever um componente que possa ser repetido.
Primeiro crie uma anotação
/**
* @Author GUOSHAOHUA093
* @Description 重试拦截
* @Date 9:14 2018/12/8
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface IsTryAgain {
int times() default 1;
Class<? extends Exception> exception() default Exception.class;
}
Um ponto de entrada no comum
/**
*@Author GUOSHAOHUA093
*@Description 重试切点
*@Date 14:07 2018/12/8
*/
@Component //声明组件
@Aspect
public class TryAgainPointcut {
@Pointcut("execution(* com.pingan.medical.service..*(..))")
public void businessService() {
}
}
Como queremos que cada nova tentativa seja uma nova transação, precisamos executá-la acima da transação e podemos julgar que tipo de exceção tentar novamente com base na exceção recebida (atualmente suporta apenas a inserção de um Ha, acompanhamento para ver o desenvolvimento do humor...).
/**
*@Author GUOSHAOHUA093
*@Description 重试拦截处理方法
*@Date 14:09 2018/12/8
*/
@Component //声明组件
@Aspect
class RetryAgainExecutor implements Ordered {
private static final Logger logger = LoggerFactory.getLogger(RetryAgainExecutor.class);
private static final int DEFAULT_MAX_RETRIES = 2;
private int maxRetries = DEFAULT_MAX_RETRIES;
private int order = 2;
public void setMaxRetries(int maxRetries) {
this.maxRetries = maxRetries;
}
public int getOrder() {
return this.order;
}
@Around("@annotation(com.pingan.medical.config.interceptor.tryAgain.IsTryAgain)")
public Object doConcurrentOperation(ProceedingJoinPoint pjp) throws Throwable {
//得到重试次数
MethodSignature signature = (MethodSignature) pjp.getSignature();
Method method = signature.getMethod();
IsTryAgain isTryAgain = method.getAnnotation(IsTryAgain.class);
int maxTimes = isTryAgain.times();
int numAttempts = 0;
Exception retryException;
do {
numAttempts++;
try {
logger.info("这是第"+numAttempts+"次访问");
return pjp.proceed();
}catch(Exception ex) {
if (isTryAgain.exception().isInstance(Object.class) || isTryAgain.exception().isInstance(ex)) {
retryException = ex;
} else {
throw ex;
}
}
}while(numAttempts < maxTimes);
throw retryException;
}
}
É muito conveniente quando você o usa. Se você escrever exceção, ele interceptará a exceção especificada. Se você não escrever, ele interceptará todas as exceções.
@IsTryAgain(times = 2,exception = CustomException.class)
@Transactional
public ApiResult test() throw CustomException(){
Observe que, se forem usadas transações, o interceptor deve ser superior à execução da transação.
É isso.