From 90a8f1d1fcbfe8b26c81803cd6daeabe5366f3cb Mon Sep 17 00:00:00 2001
From: jieyuu <645634619@qq.com>
Date: Mon, 2 Sep 2024 15:44:06 +0800
Subject: [PATCH] =?UTF-8?q?=E5=95=86=E5=93=81=E5=BA=93=E5=AD=98=E9=94=81?=
=?UTF-8?q?=E5=AE=9A=E6=8E=A5=E5=8F=A3=E5=BC=80=E5=8F=91?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../service/impl/ProductOrderServiceImpl.java | 1 -
.../net/jieyuu/config/InterceptorConfig.java | 2 +-
.../jieyuu/controller/ProductController.java | 14 ++++
.../java/net/jieyuu/mapper/ProductMapper.java | 11 ++-
.../jieyuu/request/LockProductRequest.java | 24 ++++++
.../net/jieyuu/request/OrderItemRequest.java | 20 +++++
.../net/jieyuu/service/ProductService.java | 13 ++-
.../service/impl/ProductServiceImpl.java | 84 +++++++++++++++++++
.../main/resources/mapper/ProductMapper.xml | 30 ++++---
9 files changed, 184 insertions(+), 15 deletions(-)
create mode 100644 xdclass-product-service/src/main/java/net/jieyuu/request/LockProductRequest.java
create mode 100644 xdclass-product-service/src/main/java/net/jieyuu/request/OrderItemRequest.java
diff --git a/xdclass-order-service/src/main/java/net/jieyuu/service/impl/ProductOrderServiceImpl.java b/xdclass-order-service/src/main/java/net/jieyuu/service/impl/ProductOrderServiceImpl.java
index c2a6636..1e95dfc 100644
--- a/xdclass-order-service/src/main/java/net/jieyuu/service/impl/ProductOrderServiceImpl.java
+++ b/xdclass-order-service/src/main/java/net/jieyuu/service/impl/ProductOrderServiceImpl.java
@@ -1,7 +1,6 @@
package net.jieyuu.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.sun.org.apache.bcel.internal.generic.RETURN;
import net.jieyuu.model.ProductOrderDO;
import net.jieyuu.mapper.ProductOrderMapper;
import net.jieyuu.service.ProductOrderService;
diff --git a/xdclass-product-service/src/main/java/net/jieyuu/config/InterceptorConfig.java b/xdclass-product-service/src/main/java/net/jieyuu/config/InterceptorConfig.java
index c49a418..b822aa7 100644
--- a/xdclass-product-service/src/main/java/net/jieyuu/config/InterceptorConfig.java
+++ b/xdclass-product-service/src/main/java/net/jieyuu/config/InterceptorConfig.java
@@ -16,7 +16,7 @@ public class InterceptorConfig implements WebMvcConfigurer {
registry
.addInterceptor(new LoginInterceptor())
//拦截的路径
- .addPathPatterns("/api/cart/*/**")
+ .addPathPatterns("/api/product/*/lock_products", "/api/cart/*/**")
//放行的路径
.excludePathPatterns("");
diff --git a/xdclass-product-service/src/main/java/net/jieyuu/controller/ProductController.java b/xdclass-product-service/src/main/java/net/jieyuu/controller/ProductController.java
index d3d5253..2399076 100644
--- a/xdclass-product-service/src/main/java/net/jieyuu/controller/ProductController.java
+++ b/xdclass-product-service/src/main/java/net/jieyuu/controller/ProductController.java
@@ -4,6 +4,7 @@ package net.jieyuu.controller;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
+import net.jieyuu.request.LockProductRequest;
import net.jieyuu.service.ProductService;
import net.jieyuu.utils.JsonData;
import net.jieyuu.vo.ProductVO;
@@ -46,5 +47,18 @@ public class ProductController {
return JsonData.buildSuccess(productVO);
}
+ /**
+ * 商品库存锁定
+ *
+ * @return
+ */
+ @ApiOperation("商品库存锁定")
+ @PutMapping("lock_products")
+ public JsonData lockProduct(@ApiParam("商品库存锁定") @RequestBody LockProductRequest lockProductRequest) {
+JsonData jsonData = productService.lockProductStock(lockProductRequest);
+ return jsonData;
+ }
+
+
}
diff --git a/xdclass-product-service/src/main/java/net/jieyuu/mapper/ProductMapper.java b/xdclass-product-service/src/main/java/net/jieyuu/mapper/ProductMapper.java
index bdfa33a..38620f2 100644
--- a/xdclass-product-service/src/main/java/net/jieyuu/mapper/ProductMapper.java
+++ b/xdclass-product-service/src/main/java/net/jieyuu/mapper/ProductMapper.java
@@ -2,10 +2,11 @@ package net.jieyuu.mapper;
import net.jieyuu.model.ProductDO;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Param;
/**
*
- * Mapper 接口
+ * Mapper 接口
*
*
* @author jieyuu
@@ -13,4 +14,12 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
*/
public interface ProductMapper extends BaseMapper {
+ /**
+ * 锁定商品库存
+ *
+ * @param productId
+ * @param buyNum
+ * @return
+ */
+ int lockProductStock(@Param("productId") long productId, @Param("buyNum") int buyNum);
}
diff --git a/xdclass-product-service/src/main/java/net/jieyuu/request/LockProductRequest.java b/xdclass-product-service/src/main/java/net/jieyuu/request/LockProductRequest.java
new file mode 100644
index 0000000..cde9866
--- /dev/null
+++ b/xdclass-product-service/src/main/java/net/jieyuu/request/LockProductRequest.java
@@ -0,0 +1,24 @@
+package net.jieyuu.request;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import java.util.List;
+
+@ApiModel(value = "商品锁定对象", description = "商品锁定对象协议")
+@Data
+public class LockProductRequest {
+
+
+ @ApiModelProperty(value = "订单id", example = "1233332131231321")
+ @JsonProperty("order_out_trade_no")
+ private String orderOutTradeNo;
+
+ @ApiModelProperty(value = "订单项")
+ @JsonProperty("order_item_list")
+ private List orderItemList;
+
+
+}
+
diff --git a/xdclass-product-service/src/main/java/net/jieyuu/request/OrderItemRequest.java b/xdclass-product-service/src/main/java/net/jieyuu/request/OrderItemRequest.java
new file mode 100644
index 0000000..f1e82fd
--- /dev/null
+++ b/xdclass-product-service/src/main/java/net/jieyuu/request/OrderItemRequest.java
@@ -0,0 +1,20 @@
+package net.jieyuu.request;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+@ApiModel("商品子项")
+@Data
+public class OrderItemRequest {
+
+ @ApiModelProperty(value = "商品id",example = "1")
+ @JsonProperty("product_id")
+ private long productId;
+
+ @ApiModelProperty(value = "购买数量",example = "1")
+ @JsonProperty("buy_num")
+ private int buyNum;
+
+}
\ No newline at end of file
diff --git a/xdclass-product-service/src/main/java/net/jieyuu/service/ProductService.java b/xdclass-product-service/src/main/java/net/jieyuu/service/ProductService.java
index a068096..d42a255 100644
--- a/xdclass-product-service/src/main/java/net/jieyuu/service/ProductService.java
+++ b/xdclass-product-service/src/main/java/net/jieyuu/service/ProductService.java
@@ -1,7 +1,8 @@
package net.jieyuu.service;
-import net.jieyuu.model.ProductDO;
-import com.baomidou.mybatisplus.extension.service.IService;
+
+import net.jieyuu.request.LockProductRequest;
+import net.jieyuu.utils.JsonData;
import net.jieyuu.vo.ProductVO;
import java.util.List;
@@ -41,4 +42,12 @@ public interface ProductService {
* @return
*/
List findProductByIdBatch(List productIdList);
+
+ /**
+ * 锁定商品库存
+ *
+ * @param lockProductRequest
+ * @return
+ */
+ JsonData lockProductStock(LockProductRequest lockProductRequest);
}
diff --git a/xdclass-product-service/src/main/java/net/jieyuu/service/impl/ProductServiceImpl.java b/xdclass-product-service/src/main/java/net/jieyuu/service/impl/ProductServiceImpl.java
index cc257d4..3b61bff 100644
--- a/xdclass-product-service/src/main/java/net/jieyuu/service/impl/ProductServiceImpl.java
+++ b/xdclass-product-service/src/main/java/net/jieyuu/service/impl/ProductServiceImpl.java
@@ -4,10 +4,18 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
+import net.jieyuu.enums.BizCodeEnum;
+import net.jieyuu.enums.StockTaskStateEnum;
+import net.jieyuu.exception.BizException;
+import net.jieyuu.mapper.ProductTaskMapper;
import net.jieyuu.model.ProductDO;
import net.jieyuu.mapper.ProductMapper;
+import net.jieyuu.model.ProductTaskDO;
+import net.jieyuu.request.LockProductRequest;
+import net.jieyuu.request.OrderItemRequest;
import net.jieyuu.service.ProductService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import net.jieyuu.utils.JsonData;
import net.jieyuu.vo.ProductVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
@@ -16,6 +24,7 @@ import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.function.Function;
import java.util.stream.Collectors;
/**
@@ -33,6 +42,16 @@ public class ProductServiceImpl extends ServiceImpl im
@Autowired
private ProductMapper productMapper;
+ @Autowired
+ private ProductTaskMapper productTaskMapper;
+
+ /**
+ * 分页查询商品列表
+ *
+ * @param page
+ * @param size
+ * @return
+ */
@Override
public Map page(int page, int size) {
Page pageInfo = new Page<>(page, size);
@@ -47,6 +66,12 @@ public class ProductServiceImpl extends ServiceImpl im
return pageMap;
}
+ /**
+ * 根据id找商品详情
+ *
+ * @param productId
+ * @return
+ */
@Override
public ProductVO findDetailById(long productId) {
ProductDO productDO = productMapper.selectById(productId);
@@ -54,6 +79,12 @@ public class ProductServiceImpl extends ServiceImpl im
return beanProcess(productDO);
}
+ /**
+ * 批量查询
+ *
+ * @param productIdList
+ * @return
+ */
@Override
public List findProductByIdBatch(List productIdList) {
List productDOList = productMapper.selectList(new QueryWrapper().in("id", productIdList));
@@ -61,6 +92,59 @@ public class ProductServiceImpl extends ServiceImpl im
return productVOList;
}
+ /**
+ * 锁定商品库存
+ * 1)遍历商品,锁定每个商品购买数量
+ * 2)每一次锁定的时候,都要发送延迟消息
+ *
+ * @param lockProductRequest
+ * @return
+ */
+ @Override
+ public JsonData lockProductStock(LockProductRequest lockProductRequest) {
+
+ String outTradeNo = lockProductRequest.getOrderOutTradeNo();
+ List orderItemList = lockProductRequest.getOrderItemList();
+
+ // 批量查询itemList的商品情况,减少连接
+ // 提取itemList里面的所有id
+ List productIdList = orderItemList.stream().map(OrderItemRequest::getProductId).collect(Collectors.toList());
+
+ //一次查询,结果分组
+ //批量查询商品最新数据
+ List productVOList = this.findProductByIdBatch(productIdList);
+ //根据id进行分组
+ Map productMaps = productVOList.stream().collect(Collectors.toMap(ProductVO::getId, Function.identity()));
+
+ for (OrderItemRequest item : orderItemList) {
+
+ // 锁定商品记录
+ int rows = productMapper.lockProductStock(item.getProductId(), item.getBuyNum());
+
+ if (rows != 1) {
+ throw new BizException(BizCodeEnum.ORDER_CONFIRM_LOCK_PRODUCT_FAIL);
+ } else {
+ // 插入product_task
+ ProductVO productVO = productMaps.get(item.getProductId());
+ ProductTaskDO productTaskDO = new ProductTaskDO();
+ productTaskDO.setBuyNum(item.getBuyNum());
+ productTaskDO.setLockState(StockTaskStateEnum.LOCK.name());
+ productTaskDO.setProductId(item.getProductId());
+ productTaskDO.setOutTradeNo(outTradeNo);
+
+ // 假若不需要插入商品名,那么前文批量查询就不需要了
+ // 此处为冗余字段
+ productTaskDO.setProductName(productVO.getTitle());
+
+ // 插入product_task
+ productTaskMapper.insert(productTaskDO);
+
+ // 发送MQ延迟消息, 延迟解锁商品库存 todo
+ }
+ }
+ return null;
+ }
+
private ProductVO beanProcess(ProductDO obj) {
ProductVO productVO = new ProductVO();
BeanUtils.copyProperties(obj, productVO);
diff --git a/xdclass-product-service/src/main/resources/mapper/ProductMapper.xml b/xdclass-product-service/src/main/resources/mapper/ProductMapper.xml
index adc4657..cc793b0 100644
--- a/xdclass-product-service/src/main/resources/mapper/ProductMapper.xml
+++ b/xdclass-product-service/src/main/resources/mapper/ProductMapper.xml
@@ -4,20 +4,30 @@
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
- id, title, cover_img, detail, old_amount, amount, stock, create_time, lock_stock
+ id
+ , title, cover_img, detail, old_amount, amount, stock, create_time, lock_stock
+
+
+ update product
+ set lock_stock = lock_stock + #{buyNum}
+ where id = #{productId}
+ and stock - lock_stock >={buyNum}
+
+
+