Bläddra i källkod

add
添加分布式锁

18339543638 1 år sedan
förälder
incheckning
5a10563eba

+ 37 - 0
nb-common/config-common/src/main/java/com/nb/common/lock/SpElUtil.java

@@ -0,0 +1,37 @@
+package com.nb.common.lock;
+
+import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
+import org.springframework.expression.ExpressionParser;
+import org.springframework.expression.spel.standard.SpelExpressionParser;
+import org.springframework.expression.spel.support.StandardEvaluationContext;
+
+import java.lang.reflect.Method;
+
+/**
+ * @ClassName : SpELUtil
+ * @Description :
+ * @Author : LF
+ * @Date: 2023年06月05日
+ */
+
+public class SpElUtil {
+    /**
+     * 解析
+     * @param expressionString el表达式
+     * @param method           拦截方法
+     * @param args             拦截参数
+     * @return
+     */
+    public static String parseExpression(String expressionString, Method method, Object[] args) {
+        //获取被拦截方法参数名列表
+        LocalVariableTableParameterNameDiscoverer discoverer = new LocalVariableTableParameterNameDiscoverer();
+        String[] paramNameArr = discoverer.getParameterNames(method);
+        //SPEL解析
+        ExpressionParser parser = new SpelExpressionParser();
+        StandardEvaluationContext context = new StandardEvaluationContext();
+        for (int i = 0; i < paramNameArr.length; i++) {
+            context.setVariable(paramNameArr[i], args[i]);
+        }
+        return parser.parseExpression(expressionString).getValue(context, String.class);
+    }
+}

+ 19 - 0
nb-common/config-common/src/main/java/com/nb/common/lock/TrDistributeLockAutoConfiguration.java

@@ -0,0 +1,19 @@
+package com.nb.common.lock;
+
+import com.nb.common.lock.aop.DistributeLockAspect;
+import org.redisson.api.RedissonClient;
+import org.springframework.context.annotation.Bean;
+
+/**
+ * @ClassName : TrDistributeLockAutoConfiguration
+ * @Description :
+ * @Author : LF
+ * @Date: 2023年06月05日
+ */
+
+public class TrDistributeLockAutoConfiguration {
+    @Bean
+    public DistributeLockAspect distributeLockAspect(RedissonClient redissonClient){
+        return new DistributeLockAspect(redissonClient);
+    }
+}

+ 48 - 0
nb-common/config-common/src/main/java/com/nb/common/lock/annotation/DistributeLock.java

@@ -0,0 +1,48 @@
+package com.nb.common.lock.annotation;
+
+import org.springframework.core.annotation.AliasFor;
+
+import java.lang.annotation.*;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @ClassName : DistributeLock
+ * @Description : 分布式锁注解
+ * @Author : LF
+ * @Date: 2023年06月05日
+ */
+@Target({ ElementType.METHOD })
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface DistributeLock {
+
+    @AliasFor("name")
+    String value() default "";
+
+    /**
+     * 锁名称
+     */
+    @AliasFor("value")
+    String name() default "";
+
+    /**
+     * 获取锁等待时间
+     */
+    int waitTime() default 3;
+
+    /**
+     * 释放锁时间
+     */
+
+    int leaseTime() default 10;
+
+    /**
+     * 时间单位
+     */
+    TimeUnit unit() default TimeUnit.SECONDS;
+
+    /**
+     * 重试次数
+     */
+    int retryTime() default -1;
+}

+ 62 - 0
nb-common/config-common/src/main/java/com/nb/common/lock/aop/DistributeLockAspect.java

@@ -0,0 +1,62 @@
+package com.nb.common.lock.aop;
+
+import com.nb.common.lock.SpElUtil;
+import com.nb.common.lock.annotation.DistributeLock;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.redisson.api.RLock;
+import org.redisson.api.RedissonClient;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.annotation.AnnotationUtils;
+import org.springframework.dao.CannotAcquireLockException;
+
+/**
+ * @ClassName : DistributeLockAspect
+ * @Description :
+ * @Author : LF
+ * @Date: 2023年06月05日
+ */
+@Aspect
+@Configuration
+public class DistributeLockAspect {
+    private final RedissonClient redissonClient;
+
+    public DistributeLockAspect(RedissonClient redissonClient) {
+        this.redissonClient = redissonClient;
+    }
+
+    /**
+     * 进行加锁处理
+     * @param joinPoint
+     * @param distributeLock
+     * @return
+     * @throws Throwable
+     */
+    @Around("@annotation(distributeLock)")
+    public Object around(ProceedingJoinPoint joinPoint,
+                         DistributeLock distributeLock) throws Throwable {
+        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
+        distributeLock = AnnotationUtils.findAnnotation(methodSignature.getMethod(),DistributeLock.class);
+        String key = "lock:"+ SpElUtil.parseExpression(distributeLock.name(), methodSignature.getMethod(), joinPoint.getArgs());
+        //获取锁
+        RLock rLock = redissonClient.getFairLock(key);
+        int retryTime = distributeLock.retryTime();
+        //当重试次数小于等于0时,设置为1,即获取锁的次数最少为1次
+        retryTime=retryTime<=0?1:retryTime;
+        while (retryTime>0){
+            if(rLock.tryLock(distributeLock.waitTime(),distributeLock.leaseTime(),distributeLock.unit())){
+                try {
+                    return joinPoint.proceed();
+                }finally {
+                    if(rLock.isHeldByCurrentThread()){
+                        rLock.unlock();
+                    }
+                }
+            }
+            --retryTime;
+        }
+        throw new CannotAcquireLockException("服务器繁忙,请稍后重试");
+    }
+}

+ 2 - 1
nb-common/config-common/src/main/resources/META-INF/spring.factories

@@ -1,3 +1,4 @@
 # RedisDelayQueueAutoConfiguration ×Ô¶¯×°ÅäÉùÃ÷
 org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
-com.nb.common.config.ConfigAutoConfiguration
+com.nb.common.config.ConfigAutoConfiguration,\
+com.nb.common.lock.TrDistributeLockAutoConfiguration

+ 0 - 4
nb-core/src/main/java/com/nb/core/utils/PswUtils.java

@@ -22,8 +22,4 @@ public class PswUtils {
         }
         return true;
     }
-
-    public static void main(String[] args) {
-
-    }
 }

+ 2 - 0
nb-service/app-doctor/src/main/java/com/nb/app/doctor/controller/PatientMonitorController.java

@@ -13,6 +13,7 @@ import com.nb.app.doctor.controller.vo.UpdateBindPatientVo;
 import com.nb.app.doctor.service.dto.PatientMonitorConsultResult;
 import com.nb.auth.bean.LoginUser;
 import com.nb.auth.utils.SecurityUtil;
+import com.nb.common.lock.annotation.DistributeLock;
 import com.nb.common.websocket.WebSocketSessionLifeCycleManage;
 import com.nb.core.annotation.Log;
 import com.nb.core.result.R;
@@ -91,6 +92,7 @@ public class PatientMonitorController {
 
     @ApiOperation("修改看护位置")
     @PostMapping("/edit/manage")
+    @DistributeLock(value = "#vo.clinicId",waitTime = 0)
     public R<Boolean> isOnline(@RequestBody@Validated ChangeManageVo vo){
         return R.success(patientClient.setManageType(vo.getClinicId(),vo.getManage()));
     }

+ 1 - 1
nb-service/web-service/src/main/java/com/nb/web/service/bus/listener/DeviceInfoListener.java

@@ -122,7 +122,7 @@ public class DeviceInfoListener implements IIotMsgHandler {
             //测试数据不进行病人数据的计算
             if(Boolean.FALSE.equals(infusionHistory.getTest())){
                 //格式化病号
-                formatPatientCode(device);
+//                formatPatientCode(device);
                 if(log.isDebugEnabled()){
                     log.debug("消息【{}】,设备号【{}】格式化病号,处理后结果为【{}】",device.getMsgId(),device.getDeviceId(),JSONUtil.toJsonStr(device));
                 }

+ 1 - 1
nb-service/web-service/src/main/java/com/nb/web/service/log/config/LogEventListenerConfig.java

@@ -52,7 +52,7 @@ public class LogEventListenerConfig {
         InnerLog4j2 log = logEvent.getLog();
         if(Level.ERROR.levelStr.equals(log.getLevel())){
             String exceptionStack = log.getExceptionStack();
-            if(StrUtil.containsAny(exceptionStack,"NotLoginException","Broken pipe","CustomException: ","HttpMessageNotReadableException","Stream is closed")){
+            if(StrUtil.containsAny(exceptionStack,"NotLoginException","Broken pipe","CustomException: ","HttpMessageNotReadableException","Stream is closed","CannotAcquireLockException")){
                 return;
             }
             SysRunningLog sysLog = BeanUtil.copyProperties(log, SysRunningLog.class);