update 优化 redis锁pr 代码

This commit is contained in:
疯狂的狮子li 2021-06-04 16:09:43 +08:00
parent ad6386a618
commit dcf125a08a
5 changed files with 105 additions and 135 deletions

View File

@ -1,44 +0,0 @@
package com.ruoyi.web.controller.system;
import com.ruoyi.common.annotation.RedisLock;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginBody;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.framework.web.service.TokenService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 测试分布式锁的样例
*/
@RestController
@RequestMapping("/system/redisLock")
public class RedisLockController {
@Autowired
private TokenService tokenService;
/**
* #p0 标识取第一个参数为redis锁的key
* @param loginBody
* @return
*/
@GetMapping("/getLock")
@RedisLock(expireTime=10,key = "#p0")
public AjaxResult getInfo(@RequestBody LoginBody loginBody){
LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
SysUser user = loginUser.getUser();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return AjaxResult.success(user);
}
}

View File

@ -7,6 +7,8 @@ import java.lang.annotation.Target;
/** /**
* 分布式锁注解模式不推荐使用最好用锁的工具类 * 分布式锁注解模式不推荐使用最好用锁的工具类
*
* @author shenxinquan
*/ */
@Target({ElementType.METHOD}) @Target({ElementType.METHOD})
@ -14,14 +16,12 @@ import java.lang.annotation.Target;
public @interface RedisLock { public @interface RedisLock {
/** /**
* 锁过期时间 * 锁过期时间 默认30秒
* @return
*/ */
int expireTime() default 30;//30秒 int expireTime() default 30;
/** /**
* 锁key值 * 锁key值
* @return
*/ */
String key() default "redisLockKey"; String key() default "redisLockKey";
} }

View File

@ -1,64 +0,0 @@
package com.ruoyi.common.core.redis;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
@Component
public class RedisLockUtil {
@Autowired
private RedissonClient redissonClient;
private static final String LOCK_TITLE = "redisLock_";
private static final Logger log = LoggerFactory.getLogger(RedisLockUtil.class);
/* public boolean getLock(String key){
key = LOCK_TITLE + key;
RLock mylock = redissonClient.getLock(key);
System.err.println("======lock======" + Thread.currentThread().getName());
return true;
}*/
/**
* 加锁 RLock带超时时间的
* @param key
* @param expire
* @param expireUnit
* @return
*/
public boolean acquire(String key, long expire, TimeUnit expireUnit) {
//声明key对象
key = LOCK_TITLE + key;
//获取锁对象
RLock mylock = redissonClient.getLock(key);
//加锁,并且设置锁过期时间,防止死锁的产生
try {
mylock.tryLock(expire,expire,expireUnit);
} catch (InterruptedException e) {
e.getMessage();
return false;
}
System.err.println("======lock======" + Thread.currentThread().getName());
//加锁成功
return true;
}
//锁的释放
public void release(String lockName) {
//必须是和加锁时的同一个key
String key = LOCK_TITLE + lockName;
//获取所对象
RLock mylock = redissonClient.getLock(key);
//释放锁(解锁)
mylock.unlock();
System.err.println("======unlock======" + Thread.currentThread().getName());
}
}

View File

@ -0,0 +1,35 @@
package com.ruoyi.demo.controller;
import com.ruoyi.common.annotation.RedisLock;
import com.ruoyi.common.core.domain.AjaxResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 测试分布式锁的样例
*
* @author shenxinquan
*/
@RestController
@RequestMapping("/demo/redisLock")
public class RedisLockController {
/**
* #p0 标识取第一个参数为redis锁的key
*/
@GetMapping("/getLock")
@RedisLock(expireTime = 10, key = "#p0")
public AjaxResult<String> getLock(String key, String value) {
try {
// 同时请求排队
// Thread.sleep(5000);
// 锁超时测试
Thread.sleep(11000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return AjaxResult.success("操作成功",value);
}
}

View File

@ -1,15 +1,15 @@
package com.ruoyi.common.core.redis; package com.ruoyi.framework.aspectj;
import com.ruoyi.common.annotation.RedisLock; import com.ruoyi.common.annotation.RedisLock;
import com.ruoyi.common.utils.file.ImageUtils; import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature; import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger; import org.redisson.api.RLock;
import org.slf4j.LoggerFactory; import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order; import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -21,15 +21,20 @@ import java.util.concurrent.TimeUnit;
/** /**
* 分布式锁注解实现版本 * 分布式锁注解实现版本
*
* @author shenxinquan
*/ */
@Component
@Slf4j
@Aspect @Aspect
@Order(9) @Order(9)
@Component
public class RedisLockAspect { public class RedisLockAspect {
@Autowired
private RedisLockUtil redisUtil;
private static final Logger log = LoggerFactory.getLogger(RedisLockAspect.class); @Autowired
private RedissonClient redissonClient;
private static final String LOCK_TITLE = "RedisLock_";
@Pointcut("@annotation(com.ruoyi.common.annotation.RedisLock)") @Pointcut("@annotation(com.ruoyi.common.annotation.RedisLock)")
public void annotationPointcut() { public void annotationPointcut() {
@ -47,6 +52,7 @@ public class RedisLockAspect {
String key = ""; String key = "";
// 默认30秒过期时间 // 默认30秒过期时间
int expireTime = 30; int expireTime = 30;
try { try {
// 得到访问的方法对象 // 得到访问的方法对象
Method method = className.getMethod(methodName, argClass); Method method = className.getMethod(methodName, argClass);
@ -60,18 +66,26 @@ public class RedisLockAspect {
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException("redis分布式锁注解参数异常", e); throw new RuntimeException("redis分布式锁注解参数异常", e);
} }
Object res = new Object();
if (redisUtil.acquire(key, expireTime, TimeUnit.SECONDS)) { Object res;
try { try {
res = joinPoint.proceed(); if (acquire(key, expireTime, TimeUnit.SECONDS)) {
return res; try {
} catch (Exception e) { res = joinPoint.proceed();
throw new RuntimeException(e); return res;
} finally { } catch (Exception e) {
redisUtil.release(key); throw new RuntimeException(e);
} finally {
release(key);
}
} else {
throw new RuntimeException("redis分布式锁注解参数异常");
} }
}else { } catch (IllegalMonitorStateException e) {
throw new RuntimeException("redis分布式锁注解参数异常"); log.error("lock timeout => key : " + key + " , ThreadName : " + Thread.currentThread().getName());
throw new RuntimeException("lock timeout => key : " + key);
} catch (Exception e) {
throw new Exception("redis分布式未知异常", e);
} }
} }
@ -95,9 +109,6 @@ public class RedisLockAspect {
/** /**
* 获取key中#p0中的参数名称 * 获取key中#p0中的参数名称
*
* @param key
* @return
*/ */
private static List<String> getKeyParsList(String key) { private static List<String> getKeyParsList(String key) {
List<String> listPar = new ArrayList<>(); List<String> listPar = new ArrayList<>();
@ -107,7 +118,7 @@ public class RedisLockAspect {
String parName; String parName;
int indexPre = key.indexOf("#"); int indexPre = key.indexOf("#");
if (plusIndex > 0) { if (plusIndex > 0) {
indexNext = key.indexOf("#") + key.substring(key.indexOf("#")).indexOf("+"); indexNext = key.indexOf("#") + plusIndex;
parName = key.substring(indexPre, indexNext); parName = key.substring(indexPre, indexNext);
} else { } else {
parName = key.substring(indexPre); parName = key.substring(indexPre);
@ -121,4 +132,36 @@ public class RedisLockAspect {
return listPar; return listPar;
} }
/**
* 加锁RLock带超时时间的
*/
private boolean acquire(String key, long expire, TimeUnit expireUnit) {
//声明key对象
key = LOCK_TITLE + key;
try {
//获取锁对象
RLock mylock = redissonClient.getLock(key);
//加锁,并且设置锁过期时间,防止死锁的产生
mylock.tryLock(expire, expire, expireUnit);
} catch (InterruptedException e) {
return false;
}
log.info("lock => key : " + key + " , ThreadName : " + Thread.currentThread().getName());
//加锁成功
return true;
}
/**
* 锁的释放
*/
private void release(String lockName) {
//必须是和加锁时的同一个key
String key = LOCK_TITLE + lockName;
//获取所对象
RLock mylock = redissonClient.getLock(key);
//释放锁(解锁)
mylock.unlock();
log.info("unlock => key : " + key + " , ThreadName : " + Thread.currentThread().getName());
}
} }