Browse Source

添加一个用户级锁确保解决多线程问题

ximinghao 3 months ago
parent
commit
648527561b

+ 76 - 28
src/main/java/com/skyversation/xjcy/service/AuthService.java

@@ -5,6 +5,7 @@ import com.alibaba.fastjson.JSONObject;
 import com.skyversation.xjcy.bean.User;
 import com.skyversation.xjcy.dms.DMSColumn;
 import com.skyversation.xjcy.dms.DMSService;
+import com.skyversation.xjcy.util.HashBasedLockManager;
 import com.skyversation.xjcy.util.HttpUtil;
 import com.skyversation.xjcy.util.MessageManage;
 import com.skyversation.xjcy.util.ObfuscationUtils;
@@ -139,7 +140,21 @@ public class AuthService {
             this.serviceId = serviceId;
         }
         public Account(String username, String password) {
-            this(username, password , null);
+            this(username, password, null);
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof Account) {
+                Account account = (Account) obj;
+                return username.equals(account.username) && password.equals(account.password);
+            }
+            return false;
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(username, password, serviceId);
         }
     }
 
@@ -179,6 +194,8 @@ public class AuthService {
      */
     private volatile String cacheToken;
 
+    private final HashBasedLockManager<Account> logOrRegLock = new HashBasedLockManager<>();
+
     // ============================ 构造方法 ============================
 
     public AuthService(WeChatService weChatService, PhoneService phoneService, DMSService dMSService) {
@@ -286,6 +303,10 @@ public class AuthService {
         return phoneService.sendCode(phone);
     }
 
+    public void bindEnterprise(String token, String enterpriseId) {
+
+    }
+
     // ============================ 私有方法 ============================
 
     /**
@@ -327,27 +348,29 @@ public class AuthService {
         return JSON.parseObject(response);
     }
 
-    private boolean updateRole(JSONObject userContent,Collection<String> roleIds,String serviceId){
+    private boolean updateRole(JSONObject userContent, Collection<String> addRoleIds, Collection<String> removeRoleIds, String serviceId) {
         String userId = userContent.getString(RESPONSE_FIELD_ID);
         String roleId = userContent.getString(RESPONSE_FIELD_ROLE_ID);
         String[] roleIdArr = roleId.split(",");
         Set<String> roleIdSet = new HashSet<>(Arrays.asList(roleIdArr));
-        roleIdSet.addAll(roleIds);
+        roleIdSet.addAll(addRoleIds);
+        roleIdSet.removeAll(removeRoleIds);
         String newRoleIds = String.join(",", roleIdSet);
 
         MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
         params.add("userId", userId);
         params.add("roleIds", newRoleIds);
         params.add("serviceId", serviceId);
-        Map<String,String> header = new HashMap<>();
+        Map<String, String> header = new HashMap<>();
         header.put("token", getTokenOfServiceAccount());
         String response = HttpUtil.requestPost(oauthPath + USER_UPDATE_ROLE, params, header);
         return isSuccess(JSONObject.parseObject(response));
     }
-    private void deleteUser(String userId){
+
+    private void deleteUser(String userId) {
         MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
         params.add("userId", userId);
-        Map<String,String> header = new HashMap<>();
+        Map<String, String> header = new HashMap<>();
         header.put("token", getTokenOfServiceAccount());
         HttpUtil.requestPost(oauthPath + DELETE_USER, params, header);
     }
@@ -363,7 +386,7 @@ public class AuthService {
         if (usercode == null || usercode.isEmpty()) {
             return false;
         }
-        if (!isUserDmsDataExist(usercode)) {
+        if (getUserDmsData(usercode) == null) {
             User user = new User();
             user.setCUsercode(usercode);
             boolean insertSuccess = dMSService.insertToDms(user.toJSON(), getTokenOfServiceAccount(), DMSColumn.USER);
@@ -371,8 +394,8 @@ public class AuthService {
                 allSuccess = false;
             }
         }
-        allSuccess =allSuccess&&updateRole(userContent, Collections.singletonList("41"),"11");
-        allSuccess =allSuccess&&updateRole(userContent, Collections.singletonList("45"),"12");
+        allSuccess = allSuccess && updateRole(userContent, Collections.singletonList("41"), Collections.emptyList(), "11");
+        allSuccess = allSuccess && updateRole(userContent, Collections.singletonList("45"), Collections.emptyList(), "12");
         return allSuccess;
     }
 
@@ -380,32 +403,57 @@ public class AuthService {
      * 登录或注册流程
      */
     private String logOrReg(Account account) {
-        // 尝试登录
-        JSONObject result = login(account);
-        String message = result.getString(RESPONSE_FIELD_MESSAGE);
-        boolean success = isSuccess(result);
-        if (success) {
-            return result.toJSONString();
-        } else {
-            // 登录失败处理
-            if (MESSAGE_USER_NOT_EXIST.equals(message)) {
-                boolean regSuccess = tryRegAndInit(account);
-                if (!regSuccess) {
-                    return MessageManage.getInstance().getResultContent(-1, "注册失败,未知异常", "注册失败,未知异常");
+        try {
+            return logOrRegLock.executeWithLock(account,()->{
+                // 尝试登录
+                JSONObject result = login(account);
+                String message = result.getString(RESPONSE_FIELD_MESSAGE);
+                boolean success = isSuccess(result);
+                if (success) {
+                    return result.toJSONString();
+                } else {
+                    // 登录失败处理
+                    if (MESSAGE_USER_NOT_EXIST.equals(message)) {
+                        boolean regSuccess = tryRegAndInit(account);
+                        if (!regSuccess) {
+                            return MessageManage.getInstance().getResultContent(-1, "注册失败,未知异常", "注册失败,未知异常");
+                        }
+                        return login(account).toJSONString();
+                    } else {
+                        return MessageManage.getInstance().getResultContent(-1, "未知异常", "未知异常");
+                    }
                 }
-                return login(account).toJSONString();
-            } else {
-                return MessageManage.getInstance().getResultContent(-1, "未知异常", "未知异常");
-            }
+            });
+        } catch (Exception e) {
+            throw new RuntimeException(e);
         }
     }
 
     /**
      * 检查用户账户DMS数据存在性
      */
-    private boolean isUserDmsDataExist(String userCode) {
+    private JSONObject getUserDmsData(String userCode) {
         List<JSONObject> js = dMSService.getUserJSONByCode(userCode);
-        return !js.isEmpty();
+        if (!js.isEmpty()) {
+            return js.get(0);
+        }
+        return null;
+    }
+
+    /**
+     * 升级用户为企业用户权限组
+     */
+    private void upgradeRoleEnterprise(JSONObject userContent) {
+        updateRole(userContent, Collections.singletonList("40"), Collections.emptyList(), "11");
+        updateRole(userContent, Collections.singletonList("44"), Collections.emptyList(), "12");
+    }
+
+    /**
+     * 降级用户使其失去企业用户权限组
+     */
+    private void deUpgradeRoleEnterprise(JSONObject userContent) {
+        updateRole(userContent, Collections.emptyList(), Collections.singletonList("40"), "11");
+        updateRole(userContent, Collections.emptyList(), Collections.singletonList("44"), "12");
     }
 
     /**
@@ -432,7 +480,7 @@ public class AuthService {
                 deleteUser(userId);
                 throw new RuntimeException(e);
             }
-            if (!b){
+            if (!b) {
                 deleteUser(userId);
             }
             return b;

+ 35 - 0
src/main/java/com/skyversation/xjcy/util/HashBasedLockManager.java

@@ -0,0 +1,35 @@
+package com.skyversation.xjcy.util;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+public class HashBasedLockManager<T> {
+    private final ConcurrentHashMap<Integer, Lock> lockPool;
+    private final int poolSize;
+    
+    public HashBasedLockManager(int poolSize) {
+        this.poolSize = poolSize;
+        this.lockPool = new ConcurrentHashMap<>(poolSize);
+    }
+    
+    public HashBasedLockManager() {
+        this(16); // 默认16个锁
+    }
+    
+    public <V> V executeWithLock(T key, Callable<V> task) throws Exception {
+        Lock lock = getLock(key);
+        lock.lock();
+        try {
+            return task.call();
+        } finally {
+            lock.unlock();
+        }
+    }
+    
+    private Lock getLock(T key) {
+        int lockIndex = Math.abs(key.hashCode() % poolSize);
+        return lockPool.computeIfAbsent(lockIndex, k -> new ReentrantLock());
+    }
+}