he2802 3 rokov pred
rodič
commit
0c24d983ec

+ 15 - 2
zhongzheng-api/src/main/java/com/zhongzheng/controller/cmmon/CommonController.java

@@ -3,6 +3,7 @@ package com.zhongzheng.controller.cmmon;
 import com.zhongzheng.common.core.controller.BaseController;
 import com.zhongzheng.common.core.domain.AjaxResult;
 import com.zhongzheng.common.core.page.TableDataInfo;
+import com.zhongzheng.common.core.redis.RedisCache;
 import com.zhongzheng.common.utils.ServletUtils;
 import com.zhongzheng.framework.web.service.WxTokenService;
 import com.zhongzheng.modules.course.bo.CourseMenuQueryBo;
@@ -20,6 +21,7 @@ import com.zhongzheng.modules.goods.service.IGoodsAttachedService;
 import com.zhongzheng.modules.goods.vo.GoodsAttachedVo;
 import com.zhongzheng.modules.goods.vo.GoodsUserVo;
 import com.zhongzheng.modules.order.bo.OrderAddBo;
+import com.zhongzheng.modules.order.domain.Printer;
 import com.zhongzheng.modules.order.service.IOrderGoodsService;
 import com.zhongzheng.modules.order.service.IOrderService;
 import com.zhongzheng.modules.user.entity.ClientLoginUser;
@@ -46,7 +48,8 @@ public class CommonController extends BaseController {
 
     private final ICourseService iCourseService;
 
-
+    @Autowired
+    private RedisCache redisCache;
 
 
     /**
@@ -71,6 +74,16 @@ public class CommonController extends BaseController {
         return getDataTable(list);
     }
 
-
+    @ApiOperation("查询用户拥有的商品")
+    @GetMapping("/test")
+    public AjaxResult<Integer> test(CourseQueryBo bo) throws InterruptedException {
+        System.out.print("访问");
+        Printer.num = 0;
+        new Thread(new Printer(0,redisCache)).start();
+        new Thread(new Printer(1,redisCache)).start();
+        new Thread(new Printer(2,redisCache)).start();
+        Thread.sleep(5000);
+        return AjaxResult.success(Printer.num);
+    }
 
 }

+ 64 - 5
zhongzheng-common/src/main/java/com/zhongzheng/common/core/redis/RedisCache.java

@@ -1,16 +1,17 @@
 package com.zhongzheng.common.core.redis;
 
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
 import java.util.concurrent.TimeUnit;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.io.ClassPathResource;
 import org.springframework.data.redis.core.BoundSetOperations;
 import org.springframework.data.redis.core.HashOperations;
 import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.data.redis.core.ValueOperations;
+import org.springframework.data.redis.core.script.DefaultRedisScript;
 import org.springframework.stereotype.Component;
 
 /**
@@ -25,6 +26,8 @@ public class RedisCache
     @Autowired
     public RedisTemplate redisTemplate;
 
+    protected final Logger logger = LoggerFactory.getLogger(this.getClass());
+
     /**
      * 缓存基本的对象,Integer、String、实体类等
      *
@@ -231,4 +234,60 @@ public class RedisCache
     {
         return redisTemplate.keys(pattern);
     }
+
+    /**
+     * 加锁,自旋重试三次
+     *
+     * @param redisLockEntity 锁实体
+     * @return
+     */
+    public boolean lock(RedisLockEntity redisLockEntity) {
+        boolean locked = false;
+        int tryCount = 3;
+        while (!locked && tryCount > 0) {
+            locked = redisTemplate.opsForValue().setIfAbsent(redisLockEntity.getLockKey(), redisLockEntity.getRequestId(), 2, TimeUnit.MINUTES);
+            tryCount--;
+            try {
+                Thread.sleep(400);
+            } catch (InterruptedException e) {
+                logger.error("线程被中断" + Thread.currentThread().getId());
+            }
+        }
+        return locked;
+    }
+
+    /**
+     * 非原子解锁,可能解别人锁,不安全
+     *
+     * @param redisLockEntity
+     * @return
+     */
+    public boolean unlock(RedisLockEntity redisLockEntity) {
+        if (redisLockEntity == null || redisLockEntity.getLockKey() == null || redisLockEntity.getRequestId() == null)
+            return false;
+        boolean releaseLock = false;
+        String requestId = (String) redisTemplate.opsForValue().get(redisLockEntity.getLockKey());
+        if (redisLockEntity.getRequestId().equals(requestId)) {
+            releaseLock = redisTemplate.delete(redisLockEntity.getLockKey());
+        }
+        return releaseLock;
+    }
+
+    /**
+     * 使用lua脚本解锁,不会解除别人锁
+     *
+     * @param redisLockEntity
+     * @return
+     */
+    public boolean unlockLua(RedisLockEntity redisLockEntity) {
+        if (redisLockEntity == null || redisLockEntity.getLockKey() == null || redisLockEntity.getRequestId() == null)
+            return false;
+        DefaultRedisScript<Long> redisScript = new DefaultRedisScript();
+        //用于解锁的lua脚本位置
+        redisScript.setLocation(new ClassPathResource("unlock.lua"));
+        redisScript.setResultType(Long.class);
+        //没有指定序列化方式,默认使用上面配置的
+        Object result = redisTemplate.execute(redisScript, Arrays.asList(redisLockEntity.getLockKey()), redisLockEntity.getRequestId());
+        return result.equals(Long.valueOf(1));
+    }
 }

+ 15 - 0
zhongzheng-common/src/main/java/com/zhongzheng/common/core/redis/RedisLockEntity.java

@@ -0,0 +1,15 @@
+package com.zhongzheng.common.core.redis;
+
+import lombok.Builder;
+import lombok.Data;
+import lombok.Getter;
+import lombok.Setter;
+
+@Data
+public class RedisLockEntity {
+    public static final String KEY_LOCK_GRADE ="lock_grade";  //锁班级
+
+
+    private String lockKey;
+    private String requestId;
+}

+ 5 - 0
zhongzheng-common/src/main/resources/unlock.lua

@@ -0,0 +1,5 @@
+if redis.call('get',KEYS[1]) == ARGV[1] then
+    return redis.call('del',KEYS[1])
+else
+    return 0
+end

+ 58 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/order/domain/Printer.java

@@ -0,0 +1,58 @@
+package com.zhongzheng.modules.order.domain;
+
+import com.zhongzheng.common.core.redis.RedisCache;
+import com.zhongzheng.common.core.redis.RedisLockEntity;
+import org.springframework.beans.factory.annotation.Autowired;
+
+public class Printer implements Runnable {
+
+
+     RedisCache redisCache;
+
+    int id;
+    public static int num = 1;
+
+    public Printer(int id,RedisCache redisCache) {
+        this.id = id;
+        this.redisCache = redisCache;
+    }
+
+    @Override
+    public void run() {
+/*        synchronized (Printer.class) {
+            while (num <= 75) {
+                if (num / 5 % 3 == id) {
+                    System.out.print("id" + id + ":");
+                    for (int i = 0; i < 5; i++)
+                        System.out.print(num++ + ",");
+                    System.out.println();
+                    Printer.class.notifyAll();
+                } else {
+                    try {
+                        Printer.class.wait();
+                    } catch (InterruptedException e) {
+                        e.printStackTrace();
+                    }
+                }
+            }
+        }*/
+
+        while (num <= 20) {
+            RedisLockEntity redisLockEntity = new RedisLockEntity();
+            redisLockEntity.setLockKey(RedisLockEntity.KEY_LOCK_GRADE);
+            redisLockEntity.setRequestId(id+"");
+            System.out.print("线程");
+            if(redisCache.lock(redisLockEntity)){
+                System.out.print("报数id" + id + ":"+num+"\n");
+                num++;
+                try {
+                    Thread.sleep(400);
+                } catch (InterruptedException e) {
+                    redisCache.unlockLua(redisLockEntity);
+                }
+                redisCache.unlockLua(redisLockEntity);
+            }
+
+        }
+    }
+}

+ 15 - 10
zhongzheng-system/src/main/java/com/zhongzheng/modules/order/service/impl/OrderServiceImpl.java

@@ -1,22 +1,19 @@
 package com.zhongzheng.modules.order.service.impl;
 
 import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.util.IdUtil;
 import cn.hutool.core.util.StrUtil;
 import com.alibaba.fastjson.JSON;
+import com.zhongzheng.common.core.redis.RedisCache;
+import com.zhongzheng.common.core.redis.RedisLockEntity;
 import com.zhongzheng.common.exception.CustomException;
 import com.zhongzheng.common.utils.DateUtils;
-import com.zhongzheng.common.utils.SecurityUtils;
 import com.zhongzheng.common.utils.ServletUtils;
-import com.zhongzheng.modules.alisms.service.IAliSmsService;
-import com.zhongzheng.modules.bank.domain.QuestionBusiness;
 import com.zhongzheng.modules.base.service.IProfileTpService;
 import com.zhongzheng.modules.base.service.IShoppingCartService;
-import com.zhongzheng.modules.base.vo.ProfileTpVo;
 import com.zhongzheng.modules.goods.domain.Goods;
 import com.zhongzheng.modules.goods.service.IGoodsService;
-import com.zhongzheng.modules.goods.vo.GoodsVo;
 import com.zhongzheng.modules.grade.bo.ClassGradeQueryBo;
-import com.zhongzheng.modules.grade.bo.ClassGradeUserQueryBo;
 import com.zhongzheng.modules.grade.bo.ClassGradeUserTempQueryBo;
 import com.zhongzheng.modules.grade.domain.*;
 import com.zhongzheng.modules.grade.service.IClassGradeGoodsService;
@@ -25,13 +22,10 @@ import com.zhongzheng.modules.grade.service.IClassGradeUserService;
 import com.zhongzheng.modules.grade.service.IClassGradeUserTempService;
 import com.zhongzheng.modules.grade.vo.ClassGradeUserTempVo;
 import com.zhongzheng.modules.grade.vo.ClassGradeVo;
-import com.zhongzheng.modules.inform.bo.InformUserAddBo;
 import com.zhongzheng.modules.inform.service.IInformRemindService;
 import com.zhongzheng.modules.inform.service.IInformUserService;
-import com.zhongzheng.modules.inform.vo.InformRemindVo;
 import com.zhongzheng.modules.order.bo.*;
 import com.zhongzheng.modules.order.domain.Order;
-import com.zhongzheng.modules.order.domain.OrderBusiness;
 import com.zhongzheng.modules.order.domain.OrderGoods;
 import com.zhongzheng.modules.order.mapper.OrderMapper;
 import com.zhongzheng.modules.order.service.IOrderBusinessService;
@@ -99,6 +93,9 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
     @Autowired
     private IShoppingCartService iShoppingCartService;
 
+    @Autowired
+    private RedisCache redisCache;
+
     @Autowired
     private com.zhongzheng.modules.alisms.service.IAliSmsService IAliSmsService;
 
@@ -249,7 +246,15 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
                     if(g.getGoodsInputData().getType()!=null&&g.getGoodsInputData().getType().equals("class")){
                         //判断是否购买历史班级都过期
                         canRepeatBuy =this.canBuyRepeatGoods(g.getGoodsId(),bo.getUserId());
-                        arrangeGrade(goods.getGoodsName(),goods.getGoodsId(),orderGoods.getOrderGoodsId(),gradeId,add.getUserId(),out_trade_no);
+                        String requestId = IdUtil.simpleUUID();
+                        RedisLockEntity redisLockEntity = new RedisLockEntity();
+                        redisLockEntity.setLockKey(RedisLockEntity.KEY_LOCK_GRADE);
+                        redisLockEntity.setRequestId(requestId);
+                        if(redisCache.lock(redisLockEntity)){
+                            arrangeGrade(goods.getGoodsName(),goods.getGoodsId(),orderGoods.getOrderGoodsId(),gradeId,add.getUserId(),out_trade_no);
+                            redisCache.unlockLua(redisLockEntity);
+                        }
+
                     }
                 }