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} + + +