Parcourir la source

Merge branch 'dev' into 2D展厅

licailing il y a 3 ans
Parent
commit
fea4e389bb

+ 6 - 0
src/main/java/com/izouma/nineth/config/ErrorCode.java

@@ -0,0 +1,6 @@
+package com.izouma.nineth.config;
+
+public class ErrorCode {
+    public static final int SOLD_OUT = 1001;
+    public static final int OFF_SHELF = 1002;
+}

+ 4 - 0
src/main/java/com/izouma/nineth/config/RedisKeys.java

@@ -20,4 +20,8 @@ public class RedisKeys {
     public static final String MINT_ORDER_LOCK = "mintOrderLock::";
 
     public static final String ACTIVITY_PAY_RECORD = "activityPayRecord::";
+
+    public static final String UPDATE_SALE = "updateSale";
+
+    public static final String UPDATE_STOCK = "updateSale";
 }

+ 25 - 0
src/main/java/com/izouma/nineth/domain/BlackList.java

@@ -0,0 +1,25 @@
+package com.izouma.nineth.domain;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.Entity;
+
+@Data
+@Entity
+@AllArgsConstructor
+@NoArgsConstructor
+public class BlackList extends BaseEntity {
+    private Long userId;
+
+    private String name;
+
+    private String phone;
+
+    private String ip;
+
+    private String reason;
+
+    private String ua;
+}

+ 22 - 3
src/main/java/com/izouma/nineth/listener/UpdateStockListener.java

@@ -1,5 +1,6 @@
 package com.izouma.nineth.listener;
 
+import com.izouma.nineth.config.RedisKeys;
 import com.izouma.nineth.service.CollectionService;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -7,6 +8,9 @@ import org.apache.rocketmq.spring.annotation.ConsumeMode;
 import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
 import org.apache.rocketmq.spring.core.RocketMQListener;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.data.redis.core.BoundHashOperations;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Service;
 
 @Service
@@ -18,11 +22,26 @@ import org.springframework.stereotype.Service;
         consumeMode = ConsumeMode.ORDERLY)
 @ConditionalOnProperty(value = "general.notify-server", havingValue = "false", matchIfMissing = true)
 public class UpdateStockListener implements RocketMQListener<Long> {
-
-    private CollectionService collectionService;
+    private CollectionService             collectionService;
+    private RedisTemplate<String, Object> redisTemplate;
 
     @Override
     public void onMessage(Long id) {
-        collectionService.syncStock(id);
+        BoundHashOperations<String, Long, Integer> ops = redisTemplate.boundHashOps(RedisKeys.UPDATE_SALE);
+        ops.increment(id, 1);
+    }
+
+    @Scheduled(fixedRate = 5000)
+    public void updateStock() {
+        BoundHashOperations<String, Long, Integer> ops = redisTemplate.boundHashOps(RedisKeys.UPDATE_SALE);
+        for (Long id : ops.keys()) {
+            Long val = ops.increment(id, -1);
+            if (val <= 0) {
+                ops.delete(id);
+            } else if (val > 1) {
+                ops.put(id, 1);
+            }
+            collectionService.syncStock(id);
+        }
     }
 }

+ 1 - 0
src/main/java/com/izouma/nineth/security/WebSecurityConfig.java

@@ -109,6 +109,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
                 .antMatchers("/druid/**").permitAll()
                 .antMatchers("/testmq/**").permitAll()
                 .antMatchers("/teststock/**").permitAll()
+                .antMatchers("/debounce/**").permitAll()
                 // all other requests need to be authenticated
                 .anyRequest().authenticated().and()
                 // make sure we use stateless session; session won't be used to

+ 16 - 2
src/main/java/com/izouma/nineth/service/CollectionService.java

@@ -380,6 +380,19 @@ public class CollectionService {
         return stock;
     }
 
+    public synchronized Long getStock(Long id) {
+        BoundValueOperations<String, Object> ops = redisTemplate.boundValueOps(RedisKeys.COLLECTION_STOCK + id);
+        Long stock = (Long) ops.get();
+        if (stock == null) {
+            Boolean success = ops.setIfAbsent(Optional.ofNullable(collectionRepo.getStock(id))
+                    .orElse(0), 7, TimeUnit.DAYS);
+            log.info("创建redis库存:{}", success);
+            return (Long) ops.get();
+        } else {
+            return stock;
+        }
+    }
+
     public synchronized Long decreaseStock(Long id, int number) {
         return increaseStock(id, -number);
     }
@@ -392,7 +405,8 @@ public class CollectionService {
             log.info("创建redis销量:{}", success);
         }
         Long sale = ops.increment(number);
-        rocketMQTemplate.convertAndSend(generalProperties.getUpdateSaleTopic(), id);
+        redisTemplate.opsForHash().increment(RedisKeys.UPDATE_SALE, id, 1);
+//        rocketMQTemplate.convertAndSend(generalProperties.getUpdateSaleTopic(), id);
         return sale;
     }
 
@@ -400,7 +414,7 @@ public class CollectionService {
         return increaseSale(id, -number);
     }
 
-    @Debounce(key = "#id", delay = 500)
+    //    @Debounce(key = "#id", delay = 500)
     public void syncStock(Long id) {
         Integer stock = (Integer) redisTemplate.opsForValue().get(RedisKeys.COLLECTION_STOCK + id);
         if (stock != null) {

+ 8 - 3
src/main/java/com/izouma/nineth/service/OrderService.java

@@ -109,6 +109,11 @@ public class OrderService {
             throw new BusinessException("签名已过期");
         }
 
+        Long stock = collectionService.getStock(collectionId);
+        if (stock == null || stock <= 0) {
+            throw new BusinessException("藏品已售罄", ErrorCode.SOLD_OUT);
+        }
+
         Long id = snowflakeIdWorker.nextId();
         SendResult result = rocketMQTemplate.syncSend(generalProperties.getCreateOrderTopic(),
                 new CreateOrderEvent(id, userId, collectionId, qty, addressId, userCouponId, invitor, vip), 100000);
@@ -123,15 +128,15 @@ public class OrderService {
         qty = 1;
         int stock = Optional.ofNullable(collectionService.decreaseStock(collectionId, qty))
                 .map(Math::toIntExact)
-                .orElseThrow(new BusinessException("很遗憾,藏品已售罄"));
+                .orElseThrow(new BusinessException("很遗憾,藏品已售罄", ErrorCode.SOLD_OUT));
         // 创建订单出错后需要回滚库存,所以需要try-catch
         try {
             if (stock < 0) {
-                throw new BusinessException("很遗憾,藏品已售罄");
+                throw new BusinessException("很遗憾,藏品已售罄", ErrorCode.SOLD_OUT);
             }
             Collection collection = collectionRepo.findById(collectionId).orElseThrow(new BusinessException("藏品不存在"));
             if (collection.getAssetId() != null && collection.getAssetId().equals(778359L)) {
-                throw new BusinessException("很遗憾,藏品已售罄");
+                throw new BusinessException("很遗憾,藏品已售罄", ErrorCode.SOLD_OUT);
             }
             if (collection.getAssetId() != null) {
                 Asset asset = assetRepo.findById(collection.getAssetId()).orElseThrow(new BusinessException("藏品不存在"));