content: 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();
      }
  
  
  }
  