redissonLock.unlock(CloudConstant.REDISSON_DEMO_LOCK_KEY2);
} else {
log.info("execute2获取锁失败");
}
}
2.RepeatSubmitAspect
通过公平锁判断是否是多次点击按钮 。
@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();
}
3.DistributedLockHandler
该类主要是jLock的切面类 , 通过jLock注解参数 , 判断需要加锁的类型 , 同时加锁的方法也不相同 。
//jLock切面 , 进行加锁
@SneakyThrows
@Around("@annotation(jLock)")
public Object around(ProceedingJoinPoint joinPoint, JLock jLock) {
Object obj = null;
log.info("进入RedisLock环绕通知...");
RLock rLock = getLock(joinPoint, jLock);
boolean res = false;
//获取超时时间
long expireSeconds = jLock.expireSeconds();
//等待多久,n秒内获取不到锁 , 则直接返回
long waitTime = jLock.waitTime();
//执行aop
if (rLock != null) {
try {
if (waitTime == -1) {
res = true;
//一直等待加锁
rLock.lock(expireSeconds, TimeUnit.MILLISECONDS);
} else {
res = rLock.tryLock(waitTime, expireSeconds, TimeUnit.MILLISECONDS);
}
if (res) {
obj = joinPoint.proceed();
} else {
log.error("获取锁异常");
}
} finally {
if (res) {
rLock.unlock();
}
}
}
log.info("结束RedisLock环绕通知...");
return obj;
}
//通过参数判断加锁类型
@SneakyThrows
private RLock getLock(ProceedingJoinPoint joinPoint, JLock jLock) {
//获取key
String[] keys = jLock.lockKey();
if (keys.length == 0) {
throw new RuntimeException("keys不能为空");
}
//获取参数
String[] parameterNames = new LocalVariableTableParameterNameDiscoverer().getParameterNames(((MethodSignature) joinPoint.getSignature()).getMethod());
Object[] args = joinPoint.getArgs();
LockModel lockModel = jLock.lockModel();
if (!lockModel.equals(LockModel.MULTIPLE) && !lockModel.equals(LockModel.REDLOCK) && keys.length > 1) {
throw new RuntimeException("参数有多个,锁模式为->" + lockModel.name() + ".无法锁定");
}
RLock rLock = null;
String keyConstant = jLock.keyConstant();
//判断锁类型
if (lockModel.equals(LockModel.AUTO)) {
if (keys.length > 1) {
lockModel = LockModel.REDLOCK;
} else {
lockModel = LockModel.REENTRANT;
}
}
//根据不同的锁类型执行不同的加锁方式
switch (lockModel) {
case FAIR:
rLock = redissonClient.getFairLock(getValueBySpEL(keys[0], parameterNames, args, keyConstant).get(0));
break;
case REDLOCK:
List<rlock> rLocks = new ArrayList<>();
for (String key : keys) {
List<string> valueBySpEL = getValueBySpEL(key, parameterNames, args, keyConstant);
for (String s : valueBySpEL) {
rLocks.add(redissonClient.getLock(s));
}
}
RLock[] locks = new RLock[rLocks.size()];
int index = 0;
for (RLock r : rLocks) {
locks[index++] = r;
}
rLock = new RedissonRedLock(locks);
break;
case MULTIPLE:
rLocks = new ArrayList<>();
for (String key : keys) {
List<string> valueBySpEL = getValueBySpEL(key, parameterNames, args, keyConstant);
for (String s : valueBySpEL) {
rLocks.add(redissonClient.getLock(s));
}
}
locks = new RLock[rLocks.size()];
推荐阅读
- SpringBoot项目中ES High Level Rest Client 超时问题排查及解决
- javaScript客户端签名直传
- 什么叫田径运动? 田径项目包括什么项目
- 5个冷门创业好项目 冷门创业好项目
- 做一次全面的体检,都有哪些项目? 全身检查项目
- 古天乐|被同一个项目毁掉的3位顶流男星,如今面目全非太可惜了
- 沈阳棋盘山各类冰雪项目精彩纷呈! 沈阳棋盘山滑雪
- 大学生奶茶店创业计划书 大学生创业项目计划书
- 玉米深加工做什么,玉米精深加工项目-
- 9个不起眼却很赚钱的小生意 什么项目赚钱