Bladeren bron

perf: 抽奖 抢红包

zhangqin 1 maand geleden
bovenliggende
commit
5734197922
32 gewijzigde bestanden met toevoegingen van 563 en 86 verwijderingen
  1. 10 0
      fs-common/src/main/java/com/fs/common/constant/LiveKeysConstant.java
  2. 36 23
      fs-common/src/main/java/com/fs/common/core/redis/RedisUtil.java
  3. 46 0
      fs-common/src/main/java/com/fs/common/vo/LiveVo.java
  4. 22 12
      fs-company/src/main/java/com/fs/core/aspectj/LiveControllerAspect.java
  5. 2 3
      fs-service-system/src/main/java/com/fs/live/mapper/LiveLotteryConfMapper.java
  6. 2 3
      fs-service-system/src/main/java/com/fs/live/mapper/LiveRedConfMapper.java
  7. 4 0
      fs-service-system/src/main/java/com/fs/live/mapper/LiveUserLotteryRecordMapper.java
  8. 3 0
      fs-service-system/src/main/java/com/fs/live/mapper/LiveUserRedRecordMapper.java
  9. 1 1
      fs-service-system/src/main/java/com/fs/live/service/ILiveGoodsService.java
  10. 1 1
      fs-service-system/src/main/java/com/fs/live/service/ILiveLotteryConfService.java
  11. 1 1
      fs-service-system/src/main/java/com/fs/live/service/ILiveRedConfService.java
  12. 12 2
      fs-service-system/src/main/java/com/fs/live/service/ILiveService.java
  13. 2 0
      fs-service-system/src/main/java/com/fs/live/service/ILiveUserLotteryRecordService.java
  14. 8 0
      fs-service-system/src/main/java/com/fs/live/service/ILiveUserRedRecordService.java
  15. 2 3
      fs-service-system/src/main/java/com/fs/live/service/impl/LiveGoodsServiceImpl.java
  16. 2 2
      fs-service-system/src/main/java/com/fs/live/service/impl/LiveLotteryConfServiceImpl.java
  17. 8 3
      fs-service-system/src/main/java/com/fs/live/service/impl/LiveRedConfServiceImpl.java
  18. 47 10
      fs-service-system/src/main/java/com/fs/live/service/impl/LiveServiceImpl.java
  19. 5 0
      fs-service-system/src/main/java/com/fs/live/service/impl/LiveUserLotteryRecordServiceImpl.java
  20. 5 0
      fs-service-system/src/main/java/com/fs/live/service/impl/LiveUserRedRecordServiceImpl.java
  21. 19 0
      fs-service-system/src/main/java/com/fs/live/vo/LiveConfigVo.java
  22. 6 4
      fs-user-app/src/main/java/com/fs/app/controller/LiveController.java
  23. 1 1
      fs-user-app/src/main/java/com/fs/app/controller/LiveGoodsController.java
  24. 7 1
      fs-user-app/src/main/java/com/fs/app/controller/LiveLotteryController.java
  25. 6 4
      fs-user-app/src/main/java/com/fs/app/controller/LiveRedController.java
  26. 10 0
      fs-user-app/src/main/java/com/fs/app/facade/LiveFacadeService.java
  27. 87 12
      fs-user-app/src/main/java/com/fs/app/facade/impl/LiveFacadeServiceImpl.java
  28. 1 0
      fs-user-app/src/main/java/com/fs/app/vo/LiveVo.java
  29. 56 0
      fs-user-app/src/main/java/com/fs/core/aspectj/lock/DistributeLock.java
  30. 115 0
      fs-user-app/src/main/java/com/fs/core/aspectj/lock/DistributeLockAspect.java
  31. 12 0
      fs-user-app/src/main/java/com/fs/core/aspectj/lock/DistributeLockConstant.java
  32. 24 0
      fs-user-app/src/main/java/com/fs/core/aspectj/lock/DistributeLockException.java

+ 10 - 0
fs-common/src/main/java/com/fs/common/constant/LiveKeysConstant.java

@@ -14,4 +14,14 @@ public class LiveKeysConstant {
     public static final Integer LIVE_HOME_PAGE_LIST_EXPIRE = 300; //首页缓存过期时间
     public static final String LIVE_WATCH_USERS = "live:watch:users:%s"; //在线人数
 
+    public static final String LIVE_HOME_PAGE_DETAIL = "live:detail:%s"; //直播间详情
+    public static final Integer LIVE_HOME_PAGE_DETAIL_EXPIRE = 300; //直播间详情过期时间
+
+    public static final String LIVE_HOME_PAGE_CONFIG = "live:config:%s:%s"; //直播间配置信息
+    public static final Integer LIVE_HOME_PAGE_CONFIG_EXPIRE = 300; //直播间配置信息过期时间
+    public static final String LIVE_HOME_PAGE_CONFIG_RED = "live:config:%s:red:%s"; //红包记录
+    public static final String LIVE_HOME_PAGE_CONFIG_DRAW = "live:config:%s:draw:%s"; //抽奖记录
+
+
+
 }

+ 36 - 23
fs-common/src/main/java/com/fs/common/core/redis/RedisUtil.java

@@ -24,10 +24,13 @@ public class RedisUtil {
     @Autowired
     private StringRedisTemplate stringRedisTemplate;
 
+/*    @Autowired
+    private RedissonClient redissonClient;*/
+
     /**
      * 缓存基本对象
      *
-     * @param key 缓存键
+     * @param key   缓存键
      * @param value 缓存值
      */
     public void set(String key, Object value) {
@@ -37,9 +40,9 @@ public class RedisUtil {
     /**
      * 缓存基本对象(带过期时间)
      *
-     * @param key 缓存键
-     * @param value 缓存值
-     * @param timeout 过期时间
+     * @param key      缓存键
+     * @param value    缓存值
+     * @param timeout  过期时间
      * @param timeUnit 时间单位
      */
     public void set(String key, Object value, long timeout, TimeUnit timeUnit) {
@@ -89,9 +92,9 @@ public class RedisUtil {
     /**
      * 设置过期时间
      *
-     * @param key 缓存键
+     * @param key     缓存键
      * @param timeout 过期时间
-     * @param unit 时间单位
+     * @param unit    时间单位
      * @return 是否设置成功
      */
     public boolean expire(String key, long timeout, TimeUnit unit) {
@@ -113,7 +116,7 @@ public class RedisUtil {
     /**
      * 向列表右侧添加元素
      *
-     * @param key 列表键
+     * @param key   列表键
      * @param value 元素值
      * @return 列表长度
      */
@@ -134,9 +137,9 @@ public class RedisUtil {
     /**
      * 获取列表指定范围的元素
      *
-     * @param key 列表键
+     * @param key   列表键
      * @param start 起始位置
-     * @param end 结束位置
+     * @param end   结束位置
      * @return 元素列表
      */
     public List<Object> listRange(String key, long start, long end) {
@@ -148,7 +151,7 @@ public class RedisUtil {
     /**
      * 向集合添加元素
      *
-     * @param key 集合键
+     * @param key    集合键
      * @param values 元素值
      * @return 添加成功的元素数量
      */
@@ -169,7 +172,7 @@ public class RedisUtil {
     /**
      * 判断元素是否在集合中
      *
-     * @param key 集合键
+     * @param key   集合键
      * @param value 元素值
      * @return 是否存在
      */
@@ -182,9 +185,9 @@ public class RedisUtil {
     /**
      * 向哈希表中添加键值对
      *
-     * @param key 哈希表键
+     * @param key     哈希表键
      * @param hashKey 哈希键
-     * @param value 哈希值
+     * @param value   哈希值
      */
     public void hashPut(String key, String hashKey, Object value) {
         redisTemplate.opsForHash().put(key, hashKey, value);
@@ -198,10 +201,11 @@ public class RedisUtil {
     public void hashPut(String key, Map<String, String> var2) {
         redisTemplate.opsForHash().putAll(key, var2);
     }
+
     /**
      * 获取哈希表中的值
      *
-     * @param key 哈希表键
+     * @param key     哈希表键
      * @param hashKey 哈希键
      * @return 哈希值
      */
@@ -224,7 +228,7 @@ public class RedisUtil {
     /**
      * 向有序集合添加元素
      *
-     * @param key 有序集合键
+     * @param key   有序集合键
      * @param value 元素值
      * @param score 分数
      * @return 是否添加成功
@@ -236,9 +240,9 @@ public class RedisUtil {
     /**
      * 升序获取有序集合指定范围的元素
      *
-     * @param key 有序集合键
+     * @param key   有序集合键
      * @param start 起始位置
-     * @param end 结束位置
+     * @param end   结束位置
      * @return 元素集合
      */
     public Set<Object> zSetRange(String key, long start, long end) {
@@ -248,9 +252,9 @@ public class RedisUtil {
     /**
      * 降序获取有序集合指定范围的元素
      *
-     * @param key 有序集合键
+     * @param key   有序集合键
      * @param start 起始位置
-     * @param end 结束位置
+     * @param end   结束位置
      * @return 元素集合
      */
     public Set<Object> zSetReverseRange(String key, long start, long end) {
@@ -272,7 +276,7 @@ public class RedisUtil {
     /**
      * 设置字符串值
      *
-     * @param key 键
+     * @param key   
      * @param value 值
      */
     public void setString(String key, String value) {
@@ -282,9 +286,9 @@ public class RedisUtil {
     /**
      * 设置字符串值(带过期时间)
      *
-     * @param key 键
-     * @param value 值
-     * @param timeout 过期时间
+     * @param key      
+     * @param value    
+     * @param timeout  过期时间
      * @param timeUnit 时间单位
      */
     public void setString(String key, String value, long timeout, TimeUnit timeUnit) {
@@ -300,4 +304,13 @@ public class RedisUtil {
     public String getString(String key) {
         return stringRedisTemplate.opsForValue().get(key);
     }
+
+    // ======================== 布隆过滤器 ========================
+
+    // 获取布隆过滤器
+/*    public RBloomFilter<String> getRBloomFilter(String key) {
+        RBloomFilter<String> rBloomFilter = redissonClient.getBloomFilter(key);
+        rBloomFilter.tryInit(100000L, 0.01);
+        return rBloomFilter;
+    }*/
 }

+ 46 - 0
fs-common/src/main/java/com/fs/common/vo/LiveVo.java

@@ -0,0 +1,46 @@
+package com.fs.app.vo;
+
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+@Data
+public class LiveVo {
+    private Long liveId;
+
+    private String liveName;
+
+    private String liveDesc;
+
+    private Integer showType;
+
+    private Integer status;
+
+    private Long anchorId;
+
+    private Integer liveType;
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+
+    private LocalDateTime startTime;
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+
+    private LocalDateTime finishTime;
+
+    private String liveImgUrl;
+
+    private String liveConfig;
+
+    private String videoUrl;
+
+    private String flvHlsUrl;
+
+    private Long duration;
+
+    private String qwQrCode;
+    private Long nowDuration;
+    private BigDecimal nowPri;
+    private Long storeId;
+}

+ 22 - 12
fs-company/src/main/java/com/fs/core/aspectj/LiveControllerAspect.java

@@ -1,6 +1,10 @@
 package com.fs.core.aspectj;
 
+import cn.hutool.core.util.ObjectUtil;
+import com.fs.live.domain.Live;
+import com.fs.live.domain.LiveWatchUser;
 import com.fs.live.service.ILiveService;
+import org.aspectj.lang.JoinPoint;
 import org.aspectj.lang.annotation.AfterReturning;
 import org.aspectj.lang.annotation.Aspect;
 import org.aspectj.lang.annotation.Pointcut;
@@ -18,18 +22,24 @@ public class LiveControllerAspect {
     @Autowired
     private ILiveService liveService;
 
-
-    @Pointcut("execution(* com.fs.company.controller.live.LiveController.*(..))")
-    public void liveControllerMethods() {
-        // 切入点定义
-    }
-
-    /**
-     * 在LiveController的方法执行结束后执行
-     */
-    @AfterReturning(pointcut = "liveControllerMethods()", returning = "result")
-    public void afterLiveControllerMethodExecution(Object result) {
-        logger.info("后台直播间列表变更");
+    @AfterReturning(pointcut = "execution(* com.fs.company.controller.live.LiveController.add(..)) || " +
+            "execution(* com.fs.company.controller.live.LiveController.finishLive(..)) || " +
+            "execution(* com.fs.company.controller.live.LiveController.copyLive(..)) || " +
+            "execution(* com.fs.company.controller.live.LiveController.edit(..)) || " +
+            "execution(* com.fs.company.controller.live.LiveController.remove(..)) || " +
+            "execution(* com.fs.company.controller.live.LiveController.startLive(..))",
+            returning = "result")
+    public void afterLiveControllerMethodExecution(JoinPoint joinPoint,Object result) {
+        String methodName = joinPoint.getSignature().getName();
+        Object[] args = joinPoint.getArgs();
         liveService.asyncToCache();
+        if (args[0] instanceof Live) {
+            Live live = (Live) args[0];
+            if (ObjectUtil.isNotEmpty(live) && ObjectUtil.isNotEmpty(live.getLiveId())){
+                liveService.asyncToCacheLiveDetail(live.getLiveId());
+            }
+        }
+        logger.info("后台直播间列表变更");
+
     }
 }

+ 2 - 3
fs-service-system/src/main/java/com/fs/live/mapper/LiveLotteryConfMapper.java

@@ -89,9 +89,8 @@ public interface LiveLotteryConfMapper {
     @Delete("DELETE FROM live_lottery_conf WHERE lottery_id = #{lotteryId}")
     void deleteById(Long lotteryId);
 
-    @Select("SELECT * FROM live_lottery_conf WHERE live_id = #{liveId} AND lottery_status = 1 " +
-            "AND lottery_id NOT IN (SELECT live_id FROM live_lottery_registration WHERE user_id = #{userId} AND is_win = 1)")
-    List<LiveLotteryConfVo> selectActivedLottery(@Param("liveId") Long liveId, @Param("userId") String userId);
+    @Select("SELECT * FROM live_lottery_conf WHERE live_id = #{liveId} AND lottery_status = 1 ")
+    List<LiveLotteryConfVo> selectActivedLottery(@Param("liveId") Long liveId);
 
     List<LiveLotteryConfVo> selectByLotteryIds(@Param("ids") Set<String> ids);
 

+ 2 - 3
fs-service-system/src/main/java/com/fs/live/mapper/LiveRedConfMapper.java

@@ -89,9 +89,8 @@ public interface LiveRedConfMapper {
     @Delete("DELETE FROM live_red_conf WHERE red_id = #{redId}")
     void deleteById(Long redId);
 
-    @Select("SELECT * FROM live_red_conf WHERE red_status = 1 AND live_id = #{liveId} " +
-            "AND red_id NOT IN (SELECT red_id FROM live_user_red_record WHERE user_id = #{userId})")
-    List<LiveRedConf> selectActivedRed(@Param("liveId") Long liveId, @Param("userId") String userId);
+    @Select("SELECT * FROM live_red_conf WHERE red_status = 1 AND live_id = #{liveId} ")
+    List<LiveRedConf> selectActivedRed(@Param("liveId") Long liveId);
 
     void finishRedStatusBySetIds(@Param("ids") Set<String> ids);
 }

+ 4 - 0
fs-service-system/src/main/java/com/fs/live/mapper/LiveUserLotteryRecordMapper.java

@@ -3,6 +3,7 @@ package com.fs.live.mapper;
 import java.util.List;
 
 import com.fs.live.domain.LiveUserLotteryRecord;
+import org.apache.ibatis.annotations.Select;
 
 /**
  * 直播用户中奖记录Mapper接口
@@ -58,4 +59,7 @@ public interface LiveUserLotteryRecordMapper {
      * @return 结果
      */
     int deleteLiveUserLotteryRecordByIds(Long[] ids);
+
+    @Select("SELECT EXISTS(SELECT 1 FROM live_user_lottery_record WHERE user_id = #{userId} AND red_id = #{redId})")
+    boolean existsByUserIdAndRedId(Long lotteryId, String userId);
 }

+ 3 - 0
fs-service-system/src/main/java/com/fs/live/mapper/LiveUserRedRecordMapper.java

@@ -77,4 +77,7 @@ public interface LiveUserRedRecordMapper {
     })
     @Options(useGeneratedKeys = true, keyProperty = "id")
     int insert(LiveUserRedRecord record);
+
+    @Select("SELECT EXISTS(SELECT 1 FROM live_user_red_record WHERE user_id = #{userId} AND red_id = #{redId})")
+    boolean existsByUserIdAndRedId(Long userId, String redId);
 }

+ 1 - 1
fs-service-system/src/main/java/com/fs/live/service/ILiveGoodsService.java

@@ -117,7 +117,7 @@ public interface ILiveGoodsService {
     R handleIsShowChange(LiveGoodsListVo listVo);
     LiveGoodsVo selectLiveGoodsVoByGoodsId(Long goodsId);
 
-    R showGoods(Long liveId);
+    LiveGoodsVo showGoods(Long liveId);
 
     List<LiveGoods> selectByLiveId(Long existLiveId);
 

+ 1 - 1
fs-service-system/src/main/java/com/fs/live/service/ILiveLotteryConfService.java

@@ -86,7 +86,7 @@ public interface ILiveLotteryConfService {
 
     R claimLotteryPacket(LotteryPO lottery);
 
-    List<LiveLotteryConfVo> selectActivedLottery(Long liveId, String userId);
+    List<LiveLotteryConfVo> selectActivedLottery(Long liveId);
 
     List<LiveLotteryConfVo> selectByLotteryIds(Set<String> range);
 

+ 1 - 1
fs-service-system/src/main/java/com/fs/live/service/ILiveRedConfService.java

@@ -79,7 +79,7 @@ public interface ILiveRedConfService {
 
     List<LiveRedConf> selectByLiveId(Long existLiveId);
 
-    List<LiveRedConf> selectActivedRed(Long liveId, String userId);
+    List<LiveRedConf> selectActivedRed(Long liveId);
 
     // 结算掉红包
     void finishRedStatusBySetIds(Set<String> range);

+ 12 - 2
fs-service-system/src/main/java/com/fs/live/service/ILiveService.java

@@ -1,8 +1,10 @@
 package com.fs.live.service;
 
 
+import com.fs.app.vo.LiveVo;
 import com.fs.common.core.domain.R;
 import com.fs.live.domain.Live;
+import com.fs.live.vo.LiveConfigVo;
 import com.fs.live.vo.LiveListVo;
 
 import java.util.List;
@@ -154,7 +156,7 @@ public interface ILiveService
 
     R copyLive(Live live);
 
-    R currentActivities(Long liveId, String userId);
+    LiveConfigVo currentActivities(Long liveId);
 
     List<Live> selectNoEndLiveList();
 
@@ -163,7 +165,15 @@ public interface ILiveService
     void updateStatusAndTimeBatchById(List<Live> list);
 
     /**
-     * 将直播间数据加入缓存
+     * 查询直播间数据并将直播间数据加入缓存
      */
     List<Live> asyncToCache();
+    /**
+     * 查询直播间详情并加入缓存
+     */
+    LiveVo asyncToCacheLiveDetail(Long id);
+    /**
+     * 查询直播间配并加入缓存
+     */
+    LiveConfigVo asyncToCacheLiveConfig(Long liveId);
 }

+ 2 - 0
fs-service-system/src/main/java/com/fs/live/service/ILiveUserLotteryRecordService.java

@@ -64,4 +64,6 @@ public interface ILiveUserLotteryRecordService {
      * 用户点击报名抽奖
      */
     String userLottery(Long liveId, Long lotteryId, String userId);
+
+    boolean existsByUserIdAndRedId(Long lotteryId, String userId);
 }

+ 8 - 0
fs-service-system/src/main/java/com/fs/live/service/ILiveUserRedRecordService.java

@@ -59,4 +59,12 @@ public interface ILiveUserRedRecordService {
      * @return 结果
      */
     int deleteLiveUserRedRecordById(Long id);
+
+    /**
+     * 判断用户是否领过红包
+     * @param redId
+     * @param userId
+     * @return
+     */
+    boolean existsByUserIdAndRedId(Long redId, String userId);
 }

+ 2 - 3
fs-service-system/src/main/java/com/fs/live/service/impl/LiveGoodsServiceImpl.java

@@ -147,9 +147,8 @@ public class LiveGoodsServiceImpl  implements ILiveGoodsService {
     }
 
     @Override
-    public R showGoods(Long liveId) {
-        LiveGoodsVo dto = baseMapper.showGoods(liveId);
-        return R.ok().put("data", dto);
+    public LiveGoodsVo showGoods(Long liveId) {
+        return baseMapper.showGoods(liveId);
     }
 
     @Override

+ 2 - 2
fs-service-system/src/main/java/com/fs/live/service/impl/LiveLotteryConfServiceImpl.java

@@ -228,8 +228,8 @@ public class LiveLotteryConfServiceImpl implements ILiveLotteryConfService {
     }
 
     @Override
-    public List<LiveLotteryConfVo> selectActivedLottery(Long liveId, String userId) {
-        return baseMapper.selectActivedLottery(liveId, userId);
+    public List<LiveLotteryConfVo> selectActivedLottery(Long liveId) {
+        return baseMapper.selectActivedLottery(liveId);
     }
 
     @Override

+ 8 - 3
fs-service-system/src/main/java/com/fs/live/service/impl/LiveRedConfServiceImpl.java

@@ -1,8 +1,11 @@
 package com.fs.live.service.impl;
 
 
+import cn.hutool.json.JSONUtil;
+import com.fs.common.constant.LiveKeysConstant;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.redis.RedisCache;
+import com.fs.common.core.redis.RedisUtil;
 import com.fs.common.utils.DateUtils;
 import com.fs.live.domain.LiveRedConf;
 import com.fs.live.domain.LiveUserRedRecord;
@@ -41,6 +44,8 @@ public class LiveRedConfServiceImpl implements ILiveRedConfService {
 
     @Autowired
     private RedisCache redisCache;
+    @Autowired
+    private RedisUtil redisUtil;
 
     @Autowired
     private IFsUserService userService;
@@ -230,7 +235,7 @@ public class LiveRedConfServiceImpl implements ILiveRedConfService {
             // WebSocket 通知
             //String msg = String.format("用户 %d 抢到了红包 %d,获得 %d 芳华币", userId, redId, integral);
             //WebSocketServer.notifyUsers(msg);
-
+            redisUtil.hashPut(String.format(LiveKeysConstant.LIVE_HOME_PAGE_CONFIG_RED, red.getLiveId(), red.getRedId()), String.valueOf(red.getUserId()), JSONUtil.toJsonStr(record));
             return R.ok("恭喜您成功抢到"+ integral+"芳华币");
         } catch (Exception e) {
             e.printStackTrace();
@@ -258,8 +263,8 @@ public class LiveRedConfServiceImpl implements ILiveRedConfService {
     }
 
     @Override
-    public List<LiveRedConf> selectActivedRed(Long liveId, String userId) {
-        return baseMapper.selectActivedRed(liveId, userId);
+    public List<LiveRedConf> selectActivedRed(Long liveId) {
+        return baseMapper.selectActivedRed(liveId);
     }
 
     @Override

+ 47 - 10
fs-service-system/src/main/java/com/fs/live/service/impl/LiveServiceImpl.java

@@ -1,9 +1,11 @@
 package com.fs.live.service.impl;
 
 import cn.hutool.core.thread.ThreadUtil;
+import cn.hutool.core.util.ObjectUtil;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
 
+import com.fs.app.vo.LiveVo;
 import com.fs.common.constant.LiveKeysConstant;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.redis.RedisCache;
@@ -17,9 +19,7 @@ import com.fs.live.mapper.*;
 import com.fs.live.param.LiveReplayParam;
 import com.fs.live.service.*;
 import com.fs.live.utils.ProcessManager;
-import com.fs.live.vo.LiveListVo;
-import com.fs.live.vo.LiveLotteryConfVo;
-import com.fs.live.vo.LiveLotteryProductListVo;
+import com.fs.live.vo.*;
 import com.fs.system.domain.SysConfig;
 import com.fs.system.service.ISysConfigService;
 import com.hc.openapi.tool.codec.DigestUtils;
@@ -36,6 +36,7 @@ import com.fs.common.utils.sign.Md5Utils;
 
 import java.io.IOException;
 import java.time.LocalDateTime;
+import java.time.temporal.ChronoUnit;
 import java.util.*;
 import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
@@ -101,11 +102,10 @@ public class LiveServiceImpl implements ILiveService
     }
 
     @Override
-    public R currentActivities(Long liveId,String userId) {
-        R r = liveGoodsService.showGoods(liveId);
-        Object data = r.get("data");
-        List<LiveRedConf> liveRedConfs = liveRedConfService.selectActivedRed(liveId, userId);
-        List<LiveLotteryConfVo> liveLotteryConfs = liveLotteryConfService.selectActivedLottery(liveId, userId);
+    public LiveConfigVo currentActivities(Long liveId) {
+        LiveGoodsVo liveGoodsVo = liveGoodsService.showGoods(liveId);
+        List<LiveRedConf> liveRedConfs = liveRedConfService.selectActivedRed(liveId);
+        List<LiveLotteryConfVo> liveLotteryConfs = liveLotteryConfService.selectActivedLottery(liveId);
         List<Long> lotteryIds = liveLotteryConfs.stream().map(LiveLotteryConfVo::getLotteryId).collect(Collectors.toList());
         if (!lotteryIds.isEmpty()) {
             List<LiveLotteryProductListVo> products = liveLotteryProductConfMapper.selectLiveLotteryProductConfByLotteryIds(lotteryIds);
@@ -113,8 +113,7 @@ public class LiveServiceImpl implements ILiveService
                 liveLotteryConf.setProducts(products.stream().filter(product -> product.getLotteryId().equals(liveLotteryConf.getLotteryId())).collect(Collectors.toList()));
             }
         }
-
-        return R.ok().put("red", liveRedConfs).put("lottery", liveLotteryConfs).put("goods", data);
+        return LiveConfigVo.builder().liveRedConfs(liveRedConfs).liveLotteryConfs(liveLotteryConfs).liveGoodsVo(liveGoodsVo).build();
     }
 
     @Override
@@ -149,6 +148,44 @@ public class LiveServiceImpl implements ILiveService
         return list;
     }
 
+    @Override
+    public LiveVo asyncToCacheLiveDetail(Long id) {
+        LocalDateTime now = LocalDateTime.now();
+		Live live = selectLiveByLiveId(id);
+		if(ObjectUtil.isEmpty( live) || Integer.valueOf(2).equals(live.getStatus())) {
+            return null;
+        }
+		Long storeId = liveGoodsService.getStoreIdByLiveId(live.getLiveId());
+		LiveVo liveVo = new LiveVo();
+        liveVo.setStoreId(storeId);
+		BeanUtils.copyProperties(live, liveVo);
+		liveVo.setNowDuration(200L);
+		if(live.getStatus() == 2){
+			long seconds = live.getStartTime().until(now, ChronoUnit.SECONDS);
+			liveVo.setNowDuration(seconds);
+		}
+        ThreadUtil.execute(()->{
+            log.info("同步直播间详情数据到缓存{}", id);
+            redisUtil.delete(String.format(LiveKeysConstant.LIVE_HOME_PAGE_DETAIL, live.getLiveId()));
+            redisUtil.set(String.format(LiveKeysConstant.LIVE_HOME_PAGE_DETAIL, live.getLiveId()), liveVo,LiveKeysConstant.LIVE_HOME_PAGE_DETAIL_EXPIRE, TimeUnit.SECONDS);
+            log.info("直播间数据同步到缓存完成");
+        });
+
+        return liveVo;
+    }
+
+    @Override
+    public LiveConfigVo asyncToCacheLiveConfig(Long liveId) {
+        LiveConfigVo liveConfigVo = currentActivities(liveId);
+        ThreadUtil.execute(()->{
+            log.info("同步配置信息到缓存{}", liveConfigVo);
+            redisUtil.delete(String.format(LiveKeysConstant.LIVE_HOME_PAGE_CONFIG, liveId));
+            redisUtil.set(String.format(LiveKeysConstant.LIVE_HOME_PAGE_DETAIL, liveId), liveConfigVo,LiveKeysConstant.LIVE_HOME_PAGE_CONFIG_EXPIRE, TimeUnit.SECONDS);
+            log.info("直播间数据同步到缓存完成");
+        });
+        return liveConfigVo;
+    }
+
     /**
      * 查询企业直播
      * @param liveId            直播ID

+ 5 - 0
fs-service-system/src/main/java/com/fs/live/service/impl/LiveUserLotteryRecordServiceImpl.java

@@ -148,5 +148,10 @@ public class LiveUserLotteryRecordServiceImpl implements ILiveUserLotteryRecordS
         return "参与成功";
     }
 
+    @Override
+    public boolean existsByUserIdAndRedId(Long lotteryId, String userId) {
+        return baseMapper.existsByUserIdAndRedId(lotteryId,userId);
+    }
+
 
 }

+ 5 - 0
fs-service-system/src/main/java/com/fs/live/service/impl/LiveUserRedRecordServiceImpl.java

@@ -93,4 +93,9 @@ public class LiveUserRedRecordServiceImpl implements ILiveUserRedRecordService {
     {
         return baseMapper.deleteLiveUserRedRecordById(id);
     }
+
+    @Override
+    public boolean existsByUserIdAndRedId(Long redId, String userId) {
+        return baseMapper.existsByUserIdAndRedId(redId,userId);
+    }
 }

+ 19 - 0
fs-service-system/src/main/java/com/fs/live/vo/LiveConfigVo.java

@@ -0,0 +1,19 @@
+package com.fs.live.vo;
+
+import com.fs.live.domain.LiveRedConf;
+import lombok.Builder;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+@Data
+@Builder
+public class LiveConfigVo implements Serializable {
+    // 商品信息
+    private LiveGoodsVo liveGoodsVo;
+    // 红包信息
+    private List<LiveRedConf> liveRedConfs;
+    // 抽奖信息
+    private List<LiveLotteryConfVo> liveLotteryConfs;
+}

+ 6 - 4
fs-user-app/src/main/java/com/fs/app/controller/LiveController.java

@@ -88,7 +88,7 @@ public class LiveController extends AppBaseController {
 	@GetMapping("/live")
 	@ApiResponse(code = 200, message = "", response = LiveVo.class)
 	public R live(Long id) {
-		LocalDateTime now = LocalDateTime.now();
+/*		LocalDateTime now = LocalDateTime.now();
 		Live live = liveService.selectLiveByLiveId(id);
 		if(live == null) return R.error("未找到直播");
 		if(live.getIsShow() == 2) return R.error("直播未开放");
@@ -103,7 +103,8 @@ public class LiveController extends AppBaseController {
 //		if(liveVo.getNowDuration() != null){
 //			liveVo.setNowPri(BigDecimal.valueOf(liveVo.getDuration()).divide(BigDecimal.valueOf(liveVo.getNowDuration()), 20, RoundingMode.UP));
 //		}
-		return R.ok().put("data", liveVo).put("storeId", storeId);
+		return R.ok().put("data", liveVo).put("storeId", storeId);*/
+		return liveFacadeService.liveDetail(id);
 	}
 
 	// @Login
@@ -228,8 +229,9 @@ public class LiveController extends AppBaseController {
 	@Transactional
 	@Login
 	public R currentActivities(Long liveId) {
-		String userId = getUserId();
-		return liveService.currentActivities(liveId,userId);
+/*		String userId = getUserId();
+		return liveService.currentActivities(liveId,userId);*/
+		return liveFacadeService.currentActivities(liveId,getUserId());
 	}
 
 	@GetMapping("/test")

+ 1 - 1
fs-user-app/src/main/java/com/fs/app/controller/LiveGoodsController.java

@@ -131,7 +131,7 @@ public class LiveGoodsController extends AppBaseController
     @GetMapping("/showGoods/{liveId}")
     public R showGoods(@PathVariable Long liveId)
     {
-        return liveGoodsService.showGoods(liveId);
+        return R.ok().put("data", liveGoodsService.showGoods(liveId));
     }
 
 

+ 7 - 1
fs-user-app/src/main/java/com/fs/app/controller/LiveLotteryController.java

@@ -1,6 +1,7 @@
 package com.fs.app.controller;
 
 import com.fs.app.annotation.Login;
+import com.fs.app.facade.LiveFacadeService;
 import com.fs.common.core.domain.R;
 import com.fs.live.param.LotteryPO;
 import com.fs.live.service.ILiveLotteryConfService;
@@ -16,6 +17,9 @@ public class LiveLotteryController extends AppBaseController{
 
     @Autowired
     private ILiveLotteryConfService liveLotteryConfService;
+    @Autowired
+    private LiveFacadeService liveFacadeService;
+
 
     /**
      * 参与抽奖
@@ -31,8 +35,10 @@ public class LiveLotteryController extends AppBaseController{
     @Login
     @PostMapping("/claim")
     public R claim(@RequestBody LotteryPO lottery) {
+/*        lottery.setUserId(Long.parseLong(getUserId()));
+        return liveLotteryConfService.claimLotteryPacket(lottery);*/
         lottery.setUserId(Long.parseLong(getUserId()));
-        return liveLotteryConfService.claimLotteryPacket(lottery);
+        return liveFacadeService.drawClaim(lottery);
     }
 
     /**

+ 6 - 4
fs-user-app/src/main/java/com/fs/app/controller/LiveRedController.java

@@ -1,6 +1,7 @@
 package com.fs.app.controller;
 
 import com.fs.app.annotation.Login;
+import com.fs.app.facade.LiveFacadeService;
 import com.fs.common.core.domain.R;
 import com.fs.live.param.RedPO;
 import com.fs.live.service.ILiveRedConfService;
@@ -12,19 +13,20 @@ import org.springframework.web.bind.annotation.RestController;
 
 @RestController
 @RequestMapping("/app/live/liveRed")
-public class LiveRedController extends AppBaseController{
+public class LiveRedController extends AppBaseController {
 
     @Autowired
     private ILiveRedConfService liveRedConfService;
+    @Autowired
+    private LiveFacadeService liveFacadeService;
 
     /**
      * 领取红包
-     * */
+     */
     @Login
     @PostMapping("/claim")
     public R claim(@RequestBody RedPO red) {
-        red.setUserId(Long.parseLong(getUserId()));
-        return liveRedConfService.claimRedPacket(red);
+        return liveFacadeService.redClaim(red);
     }
 
 }

+ 10 - 0
fs-user-app/src/main/java/com/fs/app/facade/LiveFacadeService.java

@@ -4,9 +4,19 @@ import com.fs.common.core.domain.R;
 import com.fs.common.core.page.PageRequest;
 import com.fs.common.core.page.TableDataInfo;
 import com.fs.live.domain.LiveWatchUser;
+import com.fs.live.param.LotteryPO;
+import com.fs.live.param.RedPO;
 
 public interface LiveFacadeService {
     R liveList(PageRequest pageRequest);
 
     TableDataInfo watchUserList(LiveWatchUser param);
+
+    R liveDetail(Long id);
+
+    R currentActivities(Long liveId, String userId);
+
+    R drawClaim(LotteryPO lottery);
+
+    R redClaim(RedPO red);
 }

+ 87 - 12
fs-user-app/src/main/java/com/fs/app/facade/impl/LiveFacadeServiceImpl.java

@@ -1,31 +1,34 @@
 package com.fs.app.facade.impl;
 
 import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.thread.ThreadUtil;
+import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson.JSON;
-import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fs.app.facade.LiveFacadeService;
+import com.fs.app.vo.LiveVo;
 import com.fs.common.constant.LiveKeysConstant;
 import com.fs.common.core.controller.BaseController;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.page.PageRequest;
 import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.core.redis.RedisUtil;
+import com.fs.core.aspectj.lock.DistributeLock;
 import com.fs.live.domain.Live;
+import com.fs.live.domain.LiveLotteryRegistration;
+import com.fs.live.domain.LiveRedConf;
 import com.fs.live.domain.LiveWatchUser;
-import com.fs.live.service.ILiveService;
-import com.fs.live.service.ILiveWatchUserService;
+import com.fs.live.param.LotteryPO;
+import com.fs.live.param.RedPO;
+import com.fs.live.service.*;
+import com.fs.live.vo.LiveConfigVo;
+import com.fs.live.vo.LiveLotteryConfVo;
 import com.fs.live.vo.LiveWatchUserVO;
 import com.github.pagehelper.PageInfo;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
+import java.util.*;
 import java.util.stream.Collectors;
 
 @Service
@@ -40,6 +43,15 @@ public class LiveFacadeServiceImpl extends BaseController implements LiveFacadeS
 
     @Autowired
     private ILiveWatchUserService liveWatchUserService;
+    @Autowired
+    private ILiveUserRedRecordService liveUserRedRecordService;
+    @Autowired
+    private ILiveUserLotteryRecordService liveUserLotteryRecordService;
+
+    @Autowired
+    private ILiveLotteryRegistrationService liveLotteryRegistrationService;
+    @Autowired
+    private ILiveRedConfService iLiveRedConfService;
 
     @Override
     public R liveList(PageRequest pageRequest) {
@@ -78,12 +90,12 @@ public class LiveFacadeServiceImpl extends BaseController implements LiveFacadeS
 
     @Override
     public TableDataInfo watchUserList(LiveWatchUser param) {
-        List<LiveWatchUserVO> liveWatchUserVOS ;
-        String setKey  = String.format(LiveKeysConstant.LIVE_WATCH_USERS, param.getLiveId());
+        List<LiveWatchUserVO> liveWatchUserVOS;
+        String setKey = String.format(LiveKeysConstant.LIVE_WATCH_USERS, param.getLiveId());
         Map<Object, Object> hashEntries = redisUtil.hashEntries(setKey);
-        if (CollUtil.isEmpty(hashEntries)){
+        if (CollUtil.isEmpty(hashEntries)) {
             liveWatchUserVOS = liveWatchUserService.asyncToCache(param.getLiveId());
-        }else {
+        } else {
             liveWatchUserVOS = hashEntries.values().stream()
                     .map(value -> {
                         try {
@@ -98,4 +110,67 @@ public class LiveFacadeServiceImpl extends BaseController implements LiveFacadeS
         }
         return getDataTable(liveWatchUserVOS);
     }
+
+    @Override
+    public R liveDetail(Long id) {
+        Object o = redisUtil.hashGet(LiveKeysConstant.LIVE_HOME_PAGE_DETAIL, String.valueOf(id));
+        LiveVo liveVo;
+        if (ObjectUtil.isNotEmpty(o)) {
+            liveVo = JSON.parseObject(o.toString(), LiveVo.class);
+
+        } else {
+            liveVo = liveService.asyncToCacheLiveDetail(id);
+        }
+        return R.ok().put("data", liveVo).put("storeId", liveVo.getStoreId());
+    }
+
+    @Override
+    public R currentActivities(Long liveId, String userId) {
+        // 直播间配置信息
+        Object oLiveConfigVo = redisUtil.get(String.format(LiveKeysConstant.LIVE_HOME_PAGE_CONFIG, liveId, liveId));
+        LiveConfigVo liveConfigVo;
+        if (ObjectUtil.isNotEmpty(oLiveConfigVo)) {
+            liveConfigVo = JSON.parseObject(oLiveConfigVo.toString(), LiveConfigVo.class);
+        } else {
+            liveConfigVo = liveService.asyncToCacheLiveConfig(liveId);
+        }
+        List<LiveRedConf> redConfs = liveConfigVo.getLiveRedConfs()
+                .stream()
+                .filter(item -> ObjectUtil.isEmpty(redisUtil.hashGet(String.format(LiveKeysConstant.LIVE_HOME_PAGE_CONFIG_RED, liveId, item.getRedId()), userId)))
+                .collect(Collectors.toList());
+        List<LiveLotteryConfVo> lotteryConfs = liveConfigVo.getLiveLotteryConfs()
+                .stream()
+                .filter(item -> ObjectUtil.isEmpty(redisUtil.hashGet(String.format(LiveKeysConstant.LIVE_HOME_PAGE_CONFIG_RED, liveId, item.getLotteryId()), userId)))
+                .collect(Collectors.toList());
+        return R.ok()
+                .put("red", redConfs)
+                .put("lottery", lotteryConfs)
+                .put("goods", liveConfigVo.getLiveGoodsVo());
+    }
+
+    @Override
+    public R redClaim(RedPO red) {
+        return iLiveRedConfService.claimRedPacket(red);
+    }
+
+    @Override
+    @DistributeLock(keyExpression = "#lottery.liveId + #lottery.userId", scene = "draw_claim")
+    public R drawClaim(LotteryPO lottery) {
+        Object o = redisUtil.hashGet(String.format(LiveKeysConstant.LIVE_HOME_PAGE_CONFIG_RED, lottery.getLiveId(), lottery.getLotteryId()), String.valueOf(lottery.getUserId()));
+        if (ObjectUtil.isNotEmpty(o)) {
+            return R.ok("您已参加抽奖活动,请等待开奖!");
+        }
+        LiveLotteryRegistration registration = new LiveLotteryRegistration();
+        Date now = new Date();
+        registration.setLiveId(lottery.getLiveId());
+        registration.setUserId(lottery.getUserId());
+        registration.setLotteryId(lottery.getLotteryId());
+        registration.setIsWin(0L);
+        registration.setRizeLevel(-1L);
+        registration.setCreateTime(now);
+        registration.setUpdateTime(now);
+        redisUtil.hashPut(String.format(LiveKeysConstant.LIVE_HOME_PAGE_CONFIG_DRAW, lottery.getLiveId(), lottery.getLotteryId()), String.valueOf(lottery.getUserId()), JSONUtil.toJsonStr(registration));
+        liveLotteryRegistrationService.insertLiveLotteryRegistration(registration);
+        return R.ok("参与抽奖成功!请在直播间等待开奖");
+    }
 }

+ 1 - 0
fs-user-app/src/main/java/com/fs/app/vo/LiveVo.java

@@ -45,4 +45,5 @@ public class LiveVo {
     private String qwQrCode;
     private Long nowDuration;
     private BigDecimal nowPri;
+    private Long storeId;
 }

+ 56 - 0
fs-user-app/src/main/java/com/fs/core/aspectj/lock/DistributeLock.java

@@ -0,0 +1,56 @@
+package com.fs.core.aspectj.lock;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 分布式锁注解
+ *
+ * @author Hollis
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface DistributeLock {
+
+    /**
+     * 锁的场景
+     *
+     * @return
+     */
+    public String scene();
+
+    /**
+     * 加锁的key,优先取key(),如果没有,则取keyExpression()
+     *
+     * @return
+     */
+    public String key() default DistributeLockConstant.NONE_KEY;
+
+    /**
+     * SPEL表达式:
+     * <pre>
+     *     #id
+     *     #insertResult.id
+     * </pre>
+     *
+     * @return
+     */
+    public String keyExpression() default DistributeLockConstant.NONE_KEY;
+
+    /**
+     * 超时时间,毫秒
+     * 默认情况下不设置超时时间,会自动续期
+     *
+     * @return
+     */
+    public int expireTime() default DistributeLockConstant.DEFAULT_EXPIRE_TIME;
+
+    /**
+     * 加锁等待时长,毫秒
+     * 默认情况下不设置等待时长,会一直等待直到获取到锁
+     * @return
+     */
+    public int waitTime() default DistributeLockConstant.DEFAULT_WAIT_TIME;
+}

+ 115 - 0
fs-user-app/src/main/java/com/fs/core/aspectj/lock/DistributeLockAspect.java

@@ -0,0 +1,115 @@
+package com.fs.core.aspectj.lock;
+
+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.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.core.StandardReflectionParameterNameDiscoverer;
+import org.springframework.core.annotation.Order;
+import org.springframework.expression.EvaluationContext;
+import org.springframework.expression.Expression;
+import org.springframework.expression.spel.standard.SpelExpressionParser;
+import org.springframework.expression.spel.support.StandardEvaluationContext;
+import org.springframework.stereotype.Component;
+
+import java.lang.reflect.Method;
+import java.util.concurrent.TimeUnit;
+
+@Aspect
+@Component
+@Order(Integer.MIN_VALUE + 1)
+public class DistributeLockAspect {
+
+    private RedissonClient redissonClient;
+
+    public DistributeLockAspect(RedissonClient redissonClient) {
+        this.redissonClient = redissonClient;
+    }
+
+    private static final Logger LOG = LoggerFactory.getLogger(DistributeLockAspect.class);
+
+    @Around("@annotation(com.fs.core.aspectj.lock.DistributeLock)")
+    public Object process(ProceedingJoinPoint pjp) throws Exception {
+        Object response = null;
+        Method method = ((MethodSignature) pjp.getSignature()).getMethod();
+        DistributeLock distributeLock = method.getAnnotation(DistributeLock.class);
+
+        String key = distributeLock.key();
+        if (DistributeLockConstant.NONE_KEY.equals(key)) {
+            if (DistributeLockConstant.NONE_KEY.equals(distributeLock.keyExpression())) {
+                throw new DistributeLockException("no lock key found...");
+            }
+            SpelExpressionParser parser = new SpelExpressionParser();
+            Expression expression = parser.parseExpression(distributeLock.keyExpression());
+
+            EvaluationContext context = new StandardEvaluationContext();
+            // 获取参数值
+            Object[] args = pjp.getArgs();
+
+            // 获取运行时参数的名称
+            StandardReflectionParameterNameDiscoverer discoverer
+                    = new StandardReflectionParameterNameDiscoverer();
+            String[] parameterNames = discoverer.getParameterNames(method);
+
+            // 将参数绑定到context中
+            if (parameterNames != null) {
+                for (int i = 0; i < parameterNames.length; i++) {
+                    context.setVariable(parameterNames[i], args[i]);
+                }
+            }
+
+            // 解析表达式,获取结果
+            key = String.valueOf(expression.getValue(context));
+        }
+
+        String scene = distributeLock.scene();
+
+        String lockKey = scene + "#" + key;
+
+        int expireTime = distributeLock.expireTime();
+        int waitTime = distributeLock.waitTime();
+        RLock rLock= redissonClient.getLock(lockKey);
+        try {
+            boolean lockResult = false;
+            if (waitTime == DistributeLockConstant.DEFAULT_WAIT_TIME) {
+                if (expireTime == DistributeLockConstant.DEFAULT_EXPIRE_TIME) {
+                    LOG.info(String.format("lock for key : %s", lockKey));
+                    rLock.lock();
+                } else {
+                    LOG.info(String.format("lock for key : %s , expire : %s", lockKey, expireTime));
+                    rLock.lock(expireTime, TimeUnit.MILLISECONDS);
+                }
+                lockResult = true;
+            } else {
+                if (expireTime == DistributeLockConstant.DEFAULT_EXPIRE_TIME) {
+                    LOG.info(String.format("try lock for key : %s , wait : %s", lockKey, waitTime));
+                    lockResult = rLock.tryLock(waitTime, TimeUnit.MILLISECONDS);
+                } else {
+                    LOG.info(String.format("try lock for key : %s , expire : %s , wait : %s", lockKey, expireTime, waitTime));
+                    lockResult = rLock.tryLock(waitTime, expireTime, TimeUnit.MILLISECONDS);
+                }
+            }
+
+            if (!lockResult) {
+                LOG.warn(String.format("lock failed for key : %s , expire : %s", lockKey, expireTime));
+                throw new DistributeLockException("acquire lock failed... key : " + lockKey);
+            }
+
+
+            LOG.info(String.format("lock success for key : %s , expire : %s", lockKey, expireTime));
+            response = pjp.proceed();
+        } catch (Throwable e) {
+            throw new Exception(e);
+        } finally {
+            if (rLock.isHeldByCurrentThread()) {
+                rLock.unlock();
+                LOG.info(String.format("unlock for key : %s , expire : %s", lockKey, expireTime));
+            }
+        }
+        return response;
+    }
+}

+ 12 - 0
fs-user-app/src/main/java/com/fs/core/aspectj/lock/DistributeLockConstant.java

@@ -0,0 +1,12 @@
+package com.fs.core.aspectj.lock;
+
+public class DistributeLockConstant {
+
+    public static final String NONE_KEY = "NONE";
+
+    public static final String DEFAULT_OWNER = "DEFAULT";
+
+    public static final int DEFAULT_EXPIRE_TIME = -1;
+
+    public static final int DEFAULT_WAIT_TIME = Integer.MAX_VALUE;
+}

+ 24 - 0
fs-user-app/src/main/java/com/fs/core/aspectj/lock/DistributeLockException.java

@@ -0,0 +1,24 @@
+package com.fs.core.aspectj.lock;
+
+
+public class DistributeLockException extends RuntimeException {
+
+    public DistributeLockException() {
+    }
+
+    public DistributeLockException(String message) {
+        super(message);
+    }
+
+    public DistributeLockException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public DistributeLockException(Throwable cause) {
+        super(cause);
+    }
+
+    public DistributeLockException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
+        super(message, cause, enableSuppression, writableStackTrace);
+    }
+}