From 645c926bbd52baa90c0a4af0d253047709c5e02c Mon Sep 17 00:00:00 2001 From: sxq <812980466@qq.com> Date: Tue, 22 Jun 2021 16:06:02 +0800 Subject: [PATCH] =?UTF-8?q?=E9=9B=86=E6=88=90lock4j=E6=A1=86=E6=9E=B6?= =?UTF-8?q?=EF=BC=8C=E5=88=A0=E9=99=A4redisson=E9=94=81=EF=BC=8C=E4=BD=BF?= =?UTF-8?q?=E7=94=A8lock4j=E7=9A=84=E9=94=81=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 7 +- ruoyi-common/pom.xml | 5 + .../ruoyi/common/annotation/RedisLock.java | 27 ---- .../demo/controller/RedisLockController.java | 52 ++----- .../ruoyi/demo/service/ITestDemoService.java | 5 + .../service/impl/TestDemoServiceImpl.java | 43 ++++++ .../framework/aspectj/RedisLockAspect.java | 137 ------------------ 7 files changed, 75 insertions(+), 201 deletions(-) delete mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/annotation/RedisLock.java delete mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RedisLockAspect.java diff --git a/pom.xml b/pom.xml index 877a3961..5fe335a1 100644 --- a/pom.xml +++ b/pom.xml @@ -30,6 +30,7 @@ 11.0 2.4.1 3.15.2 + 2.2.1 3.4.0 @@ -133,7 +134,11 @@ redisson-spring-boot-starter ${redisson.version} - + + com.baomidou + lock4j-redisson-spring-boot-starter + ${lock4j.version} + com.ruoyi diff --git a/ruoyi-common/pom.xml b/ruoyi-common/pom.xml index 39c7b8e7..e2cbd39f 100644 --- a/ruoyi-common/pom.xml +++ b/ruoyi-common/pom.xml @@ -152,6 +152,11 @@ dynamic-datasource-spring-boot-starter + + com.baomidou + lock4j-redisson-spring-boot-starter + + diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RedisLock.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RedisLock.java deleted file mode 100644 index 7b3c912f..00000000 --- a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RedisLock.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.ruoyi.common.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * 分布式锁(注解模式,不推荐使用,最好用锁的工具类) - * - * @author shenxinquan - */ - -@Target({ElementType.METHOD}) -@Retention(RetentionPolicy.RUNTIME) -public @interface RedisLock { - - /** - * 锁过期时间 默认30秒 - */ - int expireTime() default 30; - - /** - * 锁key值 - */ - String key() default "redisLockKey"; -} diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisLockController.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisLockController.java index c3c71efc..b872a5f2 100644 --- a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisLockController.java +++ b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisLockController.java @@ -1,8 +1,8 @@ package com.ruoyi.demo.controller; -import com.ruoyi.common.annotation.RedisLock; import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.redis.RedisLockManager; +import com.ruoyi.demo.service.ITestDemoService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.annotation.Cacheable; @@ -10,8 +10,6 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import java.util.concurrent.TimeUnit; - /** * 测试分布式锁的样例 @@ -24,45 +22,27 @@ import java.util.concurrent.TimeUnit; public class RedisLockController { @Autowired - private RedisLockManager redisLockManager; + private ITestDemoService testDemoService; /** - * #p0 标识取第一个参数为redis锁的key + * 测试lock4j + * @param key + * @param value + * @return */ - @GetMapping("/testLock1") - @RedisLock(expireTime = 10, key = "#p0") - public AjaxResult testLock1(String key, String value) { - try { - // 同时请求排队 -// Thread.sleep(5000); - // 锁超时测试 - Thread.sleep(11000); - } catch (InterruptedException e) { - e.printStackTrace(); - } + @GetMapping("/testLock4j") + public AjaxResult testLock4j(String key,String value){ + testDemoService.testLock4j(key); + return AjaxResult.success("操作成功",value); + } + @GetMapping("/testLock4jLockTemaplate") + public AjaxResult testLock4jLockTemaplate(String key,String value){ + testDemoService.testLock4jLockTemaplate(key); return AjaxResult.success("操作成功",value); } - /** - * 测试锁工具类 - */ - @GetMapping("/testLock2") - public AjaxResult testLock(String key, Long time) { - try { - boolean flag = redisLockManager.getLock(key, time, TimeUnit.SECONDS); - if (flag) { - log.info("获取锁成功: " + key); - Thread.sleep(3000); - redisLockManager.unLock(key); - log.info("释放锁成功: " + key); - } else { - log.error("获取锁失败: " + key); - } - } catch (InterruptedException e) { - log.error(e.getMessage()); - } - return AjaxResult.success(); - } + + /** * 测试spring-cache注解 diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/service/ITestDemoService.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/service/ITestDemoService.java index 3ab87ef5..36f300c5 100644 --- a/ruoyi-demo/src/main/java/com/ruoyi/demo/service/ITestDemoService.java +++ b/ruoyi-demo/src/main/java/com/ruoyi/demo/service/ITestDemoService.java @@ -18,6 +18,11 @@ import java.util.List; * @date 2021-05-30 */ public interface ITestDemoService extends IServicePlus { + + void testLock4j(String key); + + void testLock4jLockTemaplate(String key); + /** * 查询单个 * @return diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/service/impl/TestDemoServiceImpl.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/service/impl/TestDemoServiceImpl.java index 75f52321..8d80e39f 100644 --- a/ruoyi-demo/src/main/java/com/ruoyi/demo/service/impl/TestDemoServiceImpl.java +++ b/ruoyi-demo/src/main/java/com/ruoyi/demo/service/impl/TestDemoServiceImpl.java @@ -2,6 +2,10 @@ package com.ruoyi.demo.service.impl; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.util.StrUtil; +import com.baomidou.lock.LockInfo; +import com.baomidou.lock.LockTemplate; +import com.baomidou.lock.annotation.Lock4j; +import com.baomidou.lock.executor.RedissonLockExecutor; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.ruoyi.common.annotation.DataScope; @@ -18,8 +22,10 @@ import com.ruoyi.demo.domain.TestDemo; import com.ruoyi.demo.mapper.TestDemoMapper; import com.ruoyi.demo.service.ITestDemoService; import com.ruoyi.demo.vo.TestDemoVo; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import java.time.LocalTime; import java.util.Collection; import java.util.List; import java.util.Map; @@ -33,6 +39,43 @@ import java.util.Map; @Service public class TestDemoServiceImpl extends ServicePlusImpl implements ITestDemoService { + + @Autowired + private LockTemplate lockTemplate; + + @Override + public void testLock4jLockTemaplate(String key) { + final LockInfo lockInfo = lockTemplate.lock(key, 30000L, 5000L, RedissonLockExecutor.class); + if (null == lockInfo) { + throw new RuntimeException("业务处理中,请稍后再试"); + } + // 获取锁成功,处理业务 + try { + try { + Thread.sleep(8000); + } catch (InterruptedException e) { + // + } + System.out.println("执行简单方法1 , 当前线程:" + Thread.currentThread().getName()); + } finally { + //释放锁 + lockTemplate.releaseLock(lockInfo); + } + //结束 + } + + @Override + @Lock4j(executor = RedissonLockExecutor.class,keys = {"#key"}) + public void testLock4j(String key) { + System.out.println("start:"+key+",time:"+LocalTime.now().toString()); + try { + Thread.sleep(10000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + System.out.println("end :"+key+",time:"+LocalTime.now().toString()); + } + @Override public TestDemoVo queryById(Long id) { return getVoById(id, TestDemoVo.class); diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RedisLockAspect.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RedisLockAspect.java deleted file mode 100644 index efe628f3..00000000 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RedisLockAspect.java +++ /dev/null @@ -1,137 +0,0 @@ -package com.ruoyi.framework.aspectj; - - -import com.ruoyi.common.annotation.RedisLock; -import com.ruoyi.common.constant.Constants; -import com.ruoyi.common.core.redis.RedisLockManager; -import lombok.extern.slf4j.Slf4j; -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.springframework.beans.factory.annotation.Autowired; -import org.springframework.core.annotation.Order; -import org.springframework.stereotype.Component; - -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; - -/** - * 分布式锁(注解实现版本) - * - * @author shenxinquan - */ - -@Slf4j -@Aspect -@Order(9) -@Component -public class RedisLockAspect { - - @Autowired - private RedisLockManager redisLockManager; - - @Pointcut("@annotation(com.ruoyi.common.annotation.RedisLock)") - public void annotationPointcut() { - } - - @Around("annotationPointcut()") - public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable { - // 获得当前访问的class - Class className = joinPoint.getTarget().getClass(); - // 获得访问的方法名 - String methodName = joinPoint.getSignature().getName(); - // 得到方法的参数的类型 - Class[] argClass = ((MethodSignature) joinPoint.getSignature()).getParameterTypes(); - Object[] args = joinPoint.getArgs(); - String key = ""; - // 默认30秒过期时间 - int expireTime = 30; - - try { - // 得到访问的方法对象 - Method method = className.getMethod(methodName, argClass); - method.setAccessible(true); - // 判断是否存在@RedisLock注解 - if (method.isAnnotationPresent(RedisLock.class)) { - RedisLock annotation = method.getAnnotation(RedisLock.class); - key = getRedisKey(args, annotation.key()); - expireTime = getExpireTime(annotation); - } - } catch (Exception e) { - throw new RuntimeException("redis分布式锁注解参数异常", e); - } - - // 声明锁名称 - key = Constants.REDIS_LOCK_KEY + key; - Object res; - try { - if (redisLockManager.getLock(key, expireTime, TimeUnit.SECONDS)) { - log.info("lock => key : " + key + " , ThreadName : " + Thread.currentThread().getName()); - try { - res = joinPoint.proceed(); - return res; - } catch (Exception e) { - throw new RuntimeException(e); - } finally { - redisLockManager.unLock(key); - log.info("unlock => key : " + key + " , ThreadName : " + Thread.currentThread().getName()); - } - } else { - throw new RuntimeException("redis分布式锁注解参数异常"); - } - } catch (IllegalMonitorStateException e) { - 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); - } - } - - private int getExpireTime(RedisLock annotation) { - return annotation.expireTime(); - } - - private String getRedisKey(Object[] args, String primalKey) { - if (args.length == 0) { - return primalKey; - } - // 获取#p0...集合 - List keyList = getKeyParsList(primalKey); - for (String keyName : keyList) { - int keyIndex = Integer.parseInt(keyName.toLowerCase().replace("#p", "")); - Object parValue = args[keyIndex]; - primalKey = primalKey.replace(keyName, String.valueOf(parValue)); - } - return primalKey.replace("+", "").replace("'", ""); - } - - /** - * 获取key中#p0中的参数名称 - */ - private static List getKeyParsList(String key) { - List listPar = new ArrayList<>(); - if (key.contains("#")) { - int plusIndex = key.substring(key.indexOf("#")).indexOf("+"); - int indexNext = 0; - String parName; - int indexPre = key.indexOf("#"); - if (plusIndex > 0) { - indexNext = key.indexOf("#") + plusIndex; - parName = key.substring(indexPre, indexNext); - } else { - parName = key.substring(indexPre); - } - listPar.add(parName.trim()); - key = key.substring(indexNext + 1); - if (key.contains("#")) { - listPar.addAll(getKeyParsList(key)); - } - } - return listPar; - } - -}