Explorar o código

订单锁单独提取

lutong hai 1 mes
pai
achega
13c44bbeb2

+ 61 - 0
alien-dining/src/main/java/shop/alien/dining/service/OrderLockService.java

@@ -0,0 +1,61 @@
+package shop.alien.dining.service;
+
+/**
+ * 订单锁定服务接口
+ * 用于管理订单和结算的锁定状态,防止并发操作
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+public interface OrderLockService {
+
+    /**
+     * 锁定订单(防止多人同时下单)
+     *
+     * @param tableId 桌号ID
+     * @param userId 用户ID
+     * @return 是否锁定成功
+     */
+    boolean lockOrder(Integer tableId, Integer userId);
+
+    /**
+     * 解锁订单
+     *
+     * @param tableId 桌号ID
+     * @param userId 用户ID
+     */
+    void unlockOrder(Integer tableId, Integer userId);
+
+    /**
+     * 检查订单是否被锁定
+     *
+     * @param tableId 桌号ID
+     * @return 锁定用户ID,如果未锁定返回null
+     */
+    Integer checkOrderLock(Integer tableId);
+
+    /**
+     * 锁定订单结算(防止多人同时结算)
+     *
+     * @param orderId 订单ID
+     * @param userId 用户ID
+     * @return 是否锁定成功
+     */
+    boolean lockSettlement(Integer orderId, Integer userId);
+
+    /**
+     * 解锁订单结算
+     *
+     * @param orderId 订单ID
+     * @param userId 用户ID
+     */
+    void unlockSettlement(Integer orderId, Integer userId);
+
+    /**
+     * 检查订单结算是否被锁定
+     *
+     * @param orderId 订单ID
+     * @return 锁定用户ID,如果未锁定返回null
+     */
+    Integer checkSettlementLock(Integer orderId);
+}

+ 10 - 84
alien-dining/src/main/java/shop/alien/dining/service/impl/DiningServiceImpl.java

@@ -31,9 +31,6 @@ import java.util.stream.Collectors;
 @RequiredArgsConstructor
 public class DiningServiceImpl implements DiningService {
 
-    private static final String ORDER_LOCK_KEY_PREFIX = "order:lock:table:";
-    private static final int ORDER_LOCK_EXPIRE_SECONDS = 300; // 5分钟过期
-
     private final StoreTableMapper storeTableMapper;
     private final StoreInfoMapper storeInfoMapper;
     private final StoreCuisineMapper storeCuisineMapper;
@@ -46,6 +43,7 @@ public class DiningServiceImpl implements DiningService {
     private final BaseRedisService baseRedisService;
     private final shop.alien.dining.service.StoreOrderService storeOrderService;
     private final shop.alien.mapper.StoreOrderMapper storeOrderMapper;
+    private final shop.alien.dining.service.OrderLockService orderLockService;
 
     @Override
     public DiningPageInfoVO getDiningPageInfo(Integer tableId, Integer dinerCount) {
@@ -300,7 +298,7 @@ public class DiningServiceImpl implements DiningService {
         CartDTO cart = cartService.getCart(tableId);
 
         // 检查订单锁定
-        Integer lockUserId = checkOrderLock(tableId);
+        Integer lockUserId = orderLockService.checkOrderLock(tableId);
         boolean isLocked = lockUserId != null && !lockUserId.equals(userId);
 
         OrderConfirmVO vo = new OrderConfirmVO();
@@ -379,50 +377,17 @@ public class DiningServiceImpl implements DiningService {
 
     @Override
     public boolean lockOrder(Integer tableId, Integer userId) {
-        log.info("锁定订单, tableId={}, userId={}", tableId, userId);
-
-        String lockKey = ORDER_LOCK_KEY_PREFIX + tableId;
-        String existingLock = baseRedisService.getString(lockKey);
-        if (StringUtils.hasText(existingLock)) {
-            // 已锁定,检查是否是当前用户
-            if (existingLock.equals(String.valueOf(userId))) {
-                // 刷新过期时间
-                baseRedisService.setString(lockKey, existingLock, (long) ORDER_LOCK_EXPIRE_SECONDS);
-                return true;
-            } else {
-                // 被其他用户锁定
-                return false;
-            }
-        }
-
-        // 设置锁定
-        baseRedisService.setString(lockKey, String.valueOf(userId), (long) ORDER_LOCK_EXPIRE_SECONDS);
-        return true;
+        return orderLockService.lockOrder(tableId, userId);
     }
 
     @Override
     public void unlockOrder(Integer tableId, Integer userId) {
-        log.info("解锁订单, tableId={}, userId={}", tableId, userId);
-
-        String lockKey = ORDER_LOCK_KEY_PREFIX + tableId;
-        String existingLock = baseRedisService.getString(lockKey);
-        if (StringUtils.hasText(existingLock) && existingLock.equals(String.valueOf(userId))) {
-            baseRedisService.delete(lockKey);
-        }
+        orderLockService.unlockOrder(tableId, userId);
     }
 
     @Override
     public Integer checkOrderLock(Integer tableId) {
-        String lockKey = ORDER_LOCK_KEY_PREFIX + tableId;
-        String lockUserId = baseRedisService.getString(lockKey);
-        if (StringUtils.hasText(lockUserId)) {
-            try {
-                return Integer.parseInt(lockUserId);
-            } catch (NumberFormatException e) {
-                return null;
-            }
-        }
-        return null;
+        return orderLockService.checkOrderLock(tableId);
     }
 
     /**
@@ -535,18 +500,8 @@ public class DiningServiceImpl implements DiningService {
         shop.alien.entity.store.StoreInfo storeInfo = storeInfoMapper.selectById(order.getStoreId());
 
         // 检查结算锁定
-        String lockKey = "settlement:lock:order:" + orderId;
-        String lockUserIdStr = baseRedisService.getString(lockKey);
-        Integer lockUserId = null;
-        boolean isLocked = false;
-        if (StringUtils.hasText(lockUserIdStr)) {
-            try {
-                lockUserId = Integer.parseInt(lockUserIdStr);
-                isLocked = !lockUserId.equals(userId);
-            } catch (NumberFormatException e) {
-                // ignore
-            }
-        }
+        Integer lockUserId = orderLockService.checkSettlementLock(orderId);
+        boolean isLocked = lockUserId != null && !lockUserId.equals(userId);
 
         shop.alien.entity.store.vo.OrderSettlementVO vo = new shop.alien.entity.store.vo.OrderSettlementVO();
         vo.setOrderId(order.getId());
@@ -578,46 +533,17 @@ public class DiningServiceImpl implements DiningService {
 
     @Override
     public boolean lockSettlement(Integer orderId, Integer userId) {
-        log.info("锁定订单结算, orderId={}, userId={}", orderId, userId);
-
-        String lockKey = "settlement:lock:order:" + orderId;
-        String existingLock = baseRedisService.getString(lockKey);
-        if (StringUtils.hasText(existingLock)) {
-            if (existingLock.equals(String.valueOf(userId))) {
-                baseRedisService.setString(lockKey, existingLock, (long) ORDER_LOCK_EXPIRE_SECONDS);
-                return true;
-            } else {
-                return false;
-            }
-        }
-
-        baseRedisService.setString(lockKey, String.valueOf(userId), (long) ORDER_LOCK_EXPIRE_SECONDS);
-        return true;
+        return orderLockService.lockSettlement(orderId, userId);
     }
 
     @Override
     public void unlockSettlement(Integer orderId, Integer userId) {
-        log.info("解锁订单结算, orderId={}, userId={}", orderId, userId);
-
-        String lockKey = "settlement:lock:order:" + orderId;
-        String existingLock = baseRedisService.getString(lockKey);
-        if (StringUtils.hasText(existingLock) && existingLock.equals(String.valueOf(userId))) {
-            baseRedisService.delete(lockKey);
-        }
+        orderLockService.unlockSettlement(orderId, userId);
     }
 
     @Override
     public Integer checkSettlementLock(Integer orderId) {
-        String lockKey = "settlement:lock:order:" + orderId;
-        String lockUserId = baseRedisService.getString(lockKey);
-        if (StringUtils.hasText(lockUserId)) {
-            try {
-                return Integer.parseInt(lockUserId);
-            } catch (NumberFormatException e) {
-                return null;
-            }
-        }
-        return null;
+        return orderLockService.checkSettlementLock(orderId);
     }
 
     /**

+ 118 - 0
alien-dining/src/main/java/shop/alien/dining/service/impl/OrderLockServiceImpl.java

@@ -0,0 +1,118 @@
+package shop.alien.dining.service.impl;
+
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.springframework.util.StringUtils;
+import shop.alien.dining.config.BaseRedisService;
+import shop.alien.dining.service.OrderLockService;
+
+/**
+ * 订单锁定服务实现类
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class OrderLockServiceImpl implements OrderLockService {
+
+    private static final String ORDER_LOCK_KEY_PREFIX = "order:lock:table:";
+    private static final String SETTLEMENT_LOCK_KEY_PREFIX = "settlement:lock:order:";
+    private static final int ORDER_LOCK_EXPIRE_SECONDS = 300; // 5分钟过期
+
+    private final BaseRedisService baseRedisService;
+
+    @Override
+    public boolean lockOrder(Integer tableId, Integer userId) {
+        log.info("锁定订单, tableId={}, userId={}", tableId, userId);
+
+        String lockKey = ORDER_LOCK_KEY_PREFIX + tableId;
+        String existingLock = baseRedisService.getString(lockKey);
+        if (StringUtils.hasText(existingLock)) {
+            // 已锁定,检查是否是当前用户
+            if (existingLock.equals(String.valueOf(userId))) {
+                // 刷新过期时间
+                baseRedisService.setString(lockKey, existingLock, (long) ORDER_LOCK_EXPIRE_SECONDS);
+                return true;
+            } else {
+                // 被其他用户锁定
+                return false;
+            }
+        }
+
+        // 设置锁定
+        baseRedisService.setString(lockKey, String.valueOf(userId), (long) ORDER_LOCK_EXPIRE_SECONDS);
+        return true;
+    }
+
+    @Override
+    public void unlockOrder(Integer tableId, Integer userId) {
+        log.info("解锁订单, tableId={}, userId={}", tableId, userId);
+
+        String lockKey = ORDER_LOCK_KEY_PREFIX + tableId;
+        String existingLock = baseRedisService.getString(lockKey);
+        if (StringUtils.hasText(existingLock) && existingLock.equals(String.valueOf(userId))) {
+            baseRedisService.delete(lockKey);
+        }
+    }
+
+    @Override
+    public Integer checkOrderLock(Integer tableId) {
+        String lockKey = ORDER_LOCK_KEY_PREFIX + tableId;
+        String lockUserId = baseRedisService.getString(lockKey);
+        if (StringUtils.hasText(lockUserId)) {
+            try {
+                return Integer.parseInt(lockUserId);
+            } catch (NumberFormatException e) {
+                return null;
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public boolean lockSettlement(Integer orderId, Integer userId) {
+        log.info("锁定订单结算, orderId={}, userId={}", orderId, userId);
+
+        String lockKey = SETTLEMENT_LOCK_KEY_PREFIX + orderId;
+        String existingLock = baseRedisService.getString(lockKey);
+        if (StringUtils.hasText(existingLock)) {
+            if (existingLock.equals(String.valueOf(userId))) {
+                baseRedisService.setString(lockKey, existingLock, (long) ORDER_LOCK_EXPIRE_SECONDS);
+                return true;
+            } else {
+                return false;
+            }
+        }
+
+        baseRedisService.setString(lockKey, String.valueOf(userId), (long) ORDER_LOCK_EXPIRE_SECONDS);
+        return true;
+    }
+
+    @Override
+    public void unlockSettlement(Integer orderId, Integer userId) {
+        log.info("解锁订单结算, orderId={}, userId={}", orderId, userId);
+
+        String lockKey = SETTLEMENT_LOCK_KEY_PREFIX + orderId;
+        String existingLock = baseRedisService.getString(lockKey);
+        if (StringUtils.hasText(existingLock) && existingLock.equals(String.valueOf(userId))) {
+            baseRedisService.delete(lockKey);
+        }
+    }
+
+    @Override
+    public Integer checkSettlementLock(Integer orderId) {
+        String lockKey = SETTLEMENT_LOCK_KEY_PREFIX + orderId;
+        String lockUserId = baseRedisService.getString(lockKey);
+        if (StringUtils.hasText(lockUserId)) {
+            try {
+                return Integer.parseInt(lockUserId);
+            } catch (NumberFormatException e) {
+                return null;
+            }
+        }
+        return null;
+    }
+}

+ 5 - 5
alien-dining/src/main/java/shop/alien/dining/service/impl/StoreOrderServiceImpl.java

@@ -56,7 +56,7 @@ public class StoreOrderServiceImpl extends ServiceImpl<StoreOrderMapper, StoreOr
     private final StoreInfoMapper storeInfoMapper;
     private final StoreOrderChangeLogMapper orderChangeLogMapper;
     private final shop.alien.dining.service.SseService sseService;
-    private final shop.alien.dining.service.DiningService diningService;
+    private final shop.alien.dining.service.OrderLockService orderLockService;
 
     @Override
     public StoreOrder createOrder(CreateOrderDTO dto) {
@@ -70,7 +70,7 @@ public class StoreOrderServiceImpl extends ServiceImpl<StoreOrderMapper, StoreOr
         String userPhone = TokenUtil.getCurrentUserPhone();
 
         // 检查订单锁定状态
-        Integer lockUserId = diningService.checkOrderLock(dto.getTableId());
+        Integer lockUserId = orderLockService.checkOrderLock(dto.getTableId());
         if (lockUserId != null && !lockUserId.equals(userId)) {
             throw new RuntimeException("订单已被其他用户锁定,无法下单");
         }
@@ -316,7 +316,7 @@ public class StoreOrderServiceImpl extends ServiceImpl<StoreOrderMapper, StoreOr
 
         // 创建订单成功后,自动解锁订单锁定
         try {
-            diningService.unlockOrder(dto.getTableId(), userId);
+            orderLockService.unlockOrder(dto.getTableId(), userId);
             log.info("订单创建成功后自动解锁订单锁定, tableId={}, userId={}", dto.getTableId(), userId);
         } catch (Exception e) {
             log.warn("自动解锁订单锁定失败, tableId={}, userId={}, error={}", dto.getTableId(), userId, e.getMessage());
@@ -342,7 +342,7 @@ public class StoreOrderServiceImpl extends ServiceImpl<StoreOrderMapper, StoreOr
         }
 
         // 检查结算锁定状态
-        Integer lockUserId = diningService.checkSettlementLock(orderId);
+        Integer lockUserId = orderLockService.checkSettlementLock(orderId);
         if (lockUserId != null && !lockUserId.equals(userId)) {
             throw new RuntimeException("订单结算已被其他用户锁定,无法支付");
         }
@@ -389,7 +389,7 @@ public class StoreOrderServiceImpl extends ServiceImpl<StoreOrderMapper, StoreOr
 
         // 支付订单成功后,自动解锁结算锁定
         try {
-            diningService.unlockSettlement(orderId, userId);
+            orderLockService.unlockSettlement(orderId, userId);
             log.info("订单支付成功后自动解锁结算锁定, orderId={}, userId={}", orderId, userId);
         } catch (Exception e) {
             log.warn("自动解锁结算锁定失败, orderId={}, userId={}, error={}", orderId, userId, e.getMessage());