package org.jeecg.boot.starter.lock.aspect; /** * @author zyf */ import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; import org.jeecg.boot.starter.lock.annotation.JRepeat; import org.jeecg.boot.starter.lock.client.RedissonLockClient; import org.springframework.core.LocalVariableTableParameterNameDiscoverer; import org.springframework.stereotype.Component; import javax.annotation.Resource; import java.util.Objects; import java.util.concurrent.TimeUnit; /** * 防止重复提交分布式锁拦截器 * * @author 2019年6月18日 */ @Aspect @Component public class RepeatSubmitAspect extends BaseAspect{ @Resource private RedissonLockClient redissonLockClient; /*** * 定义controller切入点拦截规则,拦截JRepeat注解的业务方法 */ @Pointcut("@annotation(jRepeat)") public void pointCut(JRepeat jRepeat) { } /** * AOP分布式锁拦截 * * @param joinPoint * @return * @throws Exception */ @Around("pointCut(jRepeat)") public Object repeatSubmit(ProceedingJoinPoint joinPoint,JRepeat jRepeat) throws Throwable { String[] parameterNames = new LocalVariableTableParameterNameDiscoverer().getParameterNames(((MethodSignature) joinPoint.getSignature()).getMethod()); if (Objects.nonNull(jRepeat)) { // 获取参数 Object[] args = joinPoint.getArgs(); // 进行一些参数的处理,比如获取订单号,操作人id等 StringBuffer lockKeyBuffer = new StringBuffer(); String key =getValueBySpEL(jRepeat.lockKey(), parameterNames, args,"RepeatSubmit").get(0); // 公平加锁,lockTime后锁自动释放 boolean isLocked = false; try { isLocked = redissonLockClient.fairLock(key, TimeUnit.SECONDS, jRepeat.lockTime()); // 如果成功获取到锁就继续执行 if (isLocked) { // 执行进程 return joinPoint.proceed(); } else { // 未获取到锁 throw new Exception("请勿重复提交"); } } finally { // 如果锁还存在,在方法执行完成后,释放锁 if (isLocked) { redissonLockClient.unlock(key); } } } return joinPoint.proceed(); } }