谷粒商城高级篇商品服务 & 商品上架
Posted 愿你满腹经纶
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了谷粒商城高级篇商品服务 & 商品上架相关的知识,希望对你有一定的参考价值。
谷粒商城笔记合集
分布式基础篇 | 分布式高级篇 | 高可用集群篇 |
---|---|---|
===简介&环境搭建=== | ===Elasticsearch=== | |
项目简介与分布式概念(第一、二章) | Elasticsearch:全文检索(第一章) | |
基础环境搭建(第三章) | ===商品服务开发=== | |
===整合SpringCloud=== | 商品服务 & 商品上架(第二章) | |
整合SpringCloud、SpringCloud alibaba(第四、五章) | ===商城首页开发=== | |
===前端知识=== | 商城业务:首页整合、Nginx 域名访问、性能优化与压力测试 (第三、四、五章) | |
前端开发基础知识(第六章) | 缓存与分布式锁(第六章) | |
===商品服务开发=== | ===商城检索开发=== | |
商品服务开发:基础概念、三级分类(第七、八章) | 商城业务:商品检索(第七章) | |
商品服务开发:品牌管理(第九章) | ||
商品服务开发:属性分组、平台属性(第十、十一章) | ||
商品服务:商品维护(第十二、十三章) | ||
===仓储服务开发=== | ||
仓储服务:仓库维护(第十四章) | ||
基础篇总结(第十五章) |
二、商品服务 & 商品上架
2.1 存储模型分析
-
上架的商品才可以在网站展示
-
上架的商品需要可以检索
Elasticsearch:用于检索数据
logstach:存储数据
Kiban:视图化查看数据
2.2 商品Mapping
分析:商品上架在 es 中是存入 sku 还是 spu ?
- 检索的时候输入名字,是需要按照 sku 的 title进行全文检索的
- 检索使用商品规格,规格是 spu 的公共属性,每个 spu 是一样的
- 按照分类 id 进去的 都是直接列出 spu的,还可以切换
- 我们如果将 sku 的 全量信息 保存在 es 中 (包括 spu 属性),就太多量字段了
- 如果我们将 spu 以及他包含的 sku 信息保存到 es 中,也可以方
PUT product
"mappings":
"properties":
"skuId":
"type":"long"
,
"spuId":
"type":"keyword"
,
"skuTitle":
"type":"text",
"analyzer": "ik_smart"
,
"skuPrice":
"type":"keyword"
,
"skuImg":
"type":"text",
"analyzer": "ik_smart"
,
"saleCount":
"type":"long"
,
"hasStock":
"type":"boolean"
,
"hotScore":
"type":"long"
,
"brandId":
"type":"long"
,
"catelogId":
"type":"long"
,
"brandName":
"type":"keyword",
"index": false,
"doc_values": false
,
"brandImg":
"type":"keyword",
"index": false,
"doc_values": false
,
"catalogName":
"type":"keyword",
"index": false,
"doc_values": false
,
"attrs":
"type":"nested",
"properties":
"attrId":
"type":"long"
,
"attrName":
"type":"keyword",
"index":false,
"doc_values":false
,
"attrValue":
"type":"keyword"
2.3 API:商品上架⚠️💡
2.3.1 业务流程
上架前
上架后
业务流程
前端点击上架后,发送请求并带上参数 spuid
-
根据
spuid
查询pms_sku_info
表得到商品相关属性 -
根据
spuid
查询pms_product_attr_value
表得到可以用来检索的规格属性 -
从
ProductAttrValueEntity
中拿到所有的 attrId,根据 attrId 查询pms_attr
查询检索的属性 -
x根据
pms_attr
查询到检索属性后,用检索属性和 原先根据spuid
查询pms_sku_info
表得到商品相关属性进行比较,pms_sku_info
包含 从pms_attr
字段attr_id 则数据保存否则过滤 -
根据
skuIds
去查询远程仓库中是否有库存 SELECT SUM(stock-stock_locked) FROMwms_ware_sku
WHERE sku_id = 1 -
组装数据 设置 SkuEsModel
-
发送给 es 保存
2.3.1 公共服务⚠️
-
创建用于传输sku库存信息的TO,用于商品上架过程中远程获取库存信息:cn/lzwei/common/to/SkuHasStockTo.java
@Data public class SkuHasStockTo private Long skuId; private Boolean hasStock;
-
修改公共返回类R,用于商品上架过程中远程获取库存信息:cn/lzwei/common/utils/R.java
public class R<T> extends HashMap<String, Object> public <T> T getData(TypeReference<T> typeReference) Object data = get("data"); String jsonString = JSON.toJSONString(data); T t = JSON.parseObject(jsonString, typeReference); return t; public R setData(Object data) put("data",data); return this;
-
创建用于传输sku上架信息的TO,用于商品上架过程中远程保存sku信息到elasticsearch:cn/lzwei/common/to/search/SpuUpTo.java
@Data public class SpuUpTo private Long skuId; private Long spuId; private String skuTitle; private BigDecimal skuPrice; private String skuImg; private Long saleCount; private Boolean hasStock; private Long hotScore; private Long brandId; private Long catalogId; private String brandName; private String brandImg; private String catalogName; private List<Attr> attrs; @Data public static class Attr private Long attrId; private String attrName; private String attrValue;
-
新增商品上架过程中批量请求elasticsearch失败、商品上架异常的状态枚举对象:cn/lzwei/common/exception/BizCodeEnume.java
public enum BizCodeEnume PRODUCT_UP_EXCEPTION(11000,"商品上架异常");
-
新增商品状态的枚举常量类,用于商品上架成功后的状态更新:cn.lzwei.common.constant.ProductConstant.StatusEnum
public class ProductConstant public enum StatusEnum NEW_SPU(0,"新建"),SPU_UP(1,"商品上架"),SPU_DOWN(2,"商品下架"); private Integer code; private String msg; StatusEnum(Integer code,String msg) this.code=code; this.msg=msg; public Integer getCode() return code; public String getMsg() return msg;
2.3.2 仓储服务⚠️
-
创建封装sku库存状态的VO,封装商品上架远程调用通过skuId列表获取sku对应的库存状态:cn/lzwei/bilimall/ware/vo/SkuHasStockVo.java
@Data public class SkuHasStockVo private Long skuId; private Boolean hasStock;
-
WareSkuController:商品上架远程调用:通过skuId列表获取sku对应的库存信息
@RestController @RequestMapping("ware/waresku") public class WareSkuController @Autowired private WareSkuService wareSkuService; /** * 商品上架远程调用:通过skuId列表获取sku对应的库存信息 */ @PostMapping("/getSkusWareInfoBySkuIds") public R getSkusWareInfoBySkuIds(@RequestBody List<Long> skuIds) List<SkuHasStockVo> wareSkuEntities=wareSkuService.getSkusWareInfoBySkuIds(skuIds); return R.ok().setData(wareSkuEntities);
-
WareSkuService:商品上架远程调用:通过skuId列表获取sku对应的库存信息
public interface WareSkuService extends IService<WareSkuEntity> /** * 商品上架远程调用:通过skuId列表获取sku对应的库存信息 */ List<SkuHasStockVo> getSkusWareInfoBySkuIds(List<Long> skuIds);
-
WareSkuServiceImpl:商品上架远程调用:通过skuId列表获取sku对应的库存信息
@Service("wareSkuService") public class WareSkuServiceImpl extends ServiceImpl<WareSkuDao, WareSkuEntity> implements WareSkuService /** * 商品上架远程调用:通过skuId列表获取sku对应的库存信息 */ @Override public List<SkuHasStockVo> getSkusWareInfoBySkuIds(List<Long> skuIds) List<SkuHasStockVo> collect = skuIds.stream().map(skuId -> SkuHasStockVo skuHasStockVo = new SkuHasStockVo(); //1.设置skuId skuHasStockVo.setSkuId(skuId); //2.通过skuId获取剩余库存:库存量-锁定库存量 Long count = baseMapper.getStock(skuId); skuHasStockVo.setHasStock(count==null?false:count > 0); return skuHasStockVo; ).collect(Collectors.toList()); return collect;
-
WareSkuDao.java:获取sku剩余库存:库存量-锁定库存量
@Mapper public interface WareSkuDao extends BaseMapper<WareSkuEntity> //通过skuId获取剩余库存:库存量-锁定库存量 Long getStock(Long skuId);
-
WareSkuDao.xml:获取sku剩余库存:库存量-锁定库存量
<mapper namespace="cn.lzwei.bilimall.ware.dao.WareSkuDao"> <!--通过skuId获取剩余库存:库存量-锁定库存量--> <select id="getStock" resultType="java.lang.Long"> SELECT SUM(stock-stock_locked) FROM `wms_ware_sku` WHERE sku_id=#skuId </select> </mapper>
2.3.3 检索服务⚠️
-
创建常量类,保存商品索引常量:cn/lzwei/bilimall/search/constant/EsConstant.java
public class EsConstant //商品索引 public static final String PRODUCT_INDEX="product";
-
ProductSaveController
@RequestMapping("/search/save") @RestController @Slf4j public class ProductSaveController @Resource ProductSaveService productSaveService; /** * 保存商品信息 */ @PostMapping("/product") public R productStatusUp(@RequestBody List<SpuUpTo> spuUpTo) boolean b=false; try b = productSaveService.productStatusUp(spuUpTo); catch (IOException e) log.error("ProductSaveController商品上架错误:",e); return R.error(BizCodeEnume.PRODUCT_UP_EXCEPTION.getCode(),BizCodeEnume.PRODUCT_UP_EXCEPTION.getMessage()); if (!b) return R.ok(); else return R.error(BizCodeEnume.PRODUCT_UP_EXCEPTION.getCode(),BizCodeEnume.PRODUCT_UP_EXCEPTION.getMessage());
-
ProductSaveService
public interface ProductSaveService /** * 保存商品信息 */ boolean productStatusUp(List<SpuUpTo> spuUpTo) throws IOException;
-
ProductSaveServiceImpl
@Service("productSaveService") @Slf4j public class ProductSaveServiceImpl implements ProductSaveService @Resource RestHighLevelClient restHighLevelClient; /** * 保存商品信息 */ @Override public boolean productStatusUp(List<SpuUpTo> spuUpTo) throws IOException //1.构造批量请求 BulkRequest bulkRequest = new BulkRequest(); for (SpuUpTo upTo : spuUpTo) //1.1、构造请求 指定es索引 IndexRequest indexRequest = new IndexRequest(EsConstant.PRODUCT_INDEX); //1.2、设置id indexRequest.id(String.valueOf(upTo.getSkuId())); //1.3、设置数据 String s = JSON.toJSONString(upTo); indexRequest.source(s, XContentType.JSON); //1.4、添加请求 bulkRequest.add(indexRequest); //2.执行批量请求 BulkResponse bulk = restHighLevelClient.bulk(bulkRequest, BilimallElasticsearchConfig.COMMON_OPTIONS); boolean b = bulk.hasFailures(); //获取上架的skuId List<String> collect = Arrays.stream(bulk.getItems()).map(item -> return item.getId(); ).collect(Collectors.toList()); //3.如果批量错误 //TODO 商品上架错误 if (b) log.error("商品上架错误:",collect); else log.info("商品上架成功的打印:",collect); return b;
2.3.4 商品服务💡
-
SpuInfoController:将所属的sku信息保存到elasticsearch中
@RestController @RequestMapping("product/spuinfo") public class SpuInfoController @Autowired private SpuInfoService spuInfoService; /** * 商品上架:将所属的sku信息保存到elasticsearch中 */ @PostMapping("/spuId/up") public R up(@PathVariable(value = "spuId") Long spuId) R r=spuInfoService.up(spuId); return r;
-
SpuInfoService:将所属的sku信息保存到elasticsearch中
public interface SpuInfoService extends IService<SpuInfoEntity> /** * 商品上架:将所属的sku信息保存到elasticsearch中 */ R up(Long spuId);
-
SpuInfoServiceImpl:将所属的sku信息保存到elasticsearch中
@Service("spuInfoService") public class SpuInfoServiceImpl extends ServiceImpl<SpuInfoDao, SpuInfoEntity> implements SpuInfoService @Resource ProductAttrValueService productAttrValueService; @Resource AttrService attrService; @Resource SkuInfoService skuInfoService; @Resource BrandService brandService; @Resource CategoryService categoryService; @Resource WareFeignService wareFeignService; @Resource SearchFeignService searchFeignService; /** * 商品上架:将所属的sku信息保存到elasticsearch中 */ @Transactional @Override public R up(Long spuId) //1.准备spu的品牌信息、分类信息:通过spuId获取品牌信息、分类信息 SpuInfoEntity spuInfo = this.getById(spuId); Long brandId = spuInfo.getBrandId(); Long catalogId = spuInfo.getCatalogId(); BrandEntity brandInfo = brandService.getById(brandId); CategoryEntity categoryInfo = categoryService.getById(catalogId); //2.准备spu的所有可检索的规格参数 //获取商品的所有规格参数 List<ProductAttrValueEntity> productAttrValueEntities = productAttrValueService.list(new QueryWrapper<ProductAttrValueEntity>().eq("spu_id", spuId)); List<Long> productAttrIds = productAttrValueEntities.stream().map(item -> item.getAttrId()).collect(Collectors.toList()); //获取可用于检索的规格参数 List<Long> searchAttrIds = attrService.getSearchAttr(productAttrIds); HashSet<Long> searchAttrIdsSet=new HashSet<>(searchAttrIds); //过滤出商品的所有可用于检索的规格参数 List<SpuUpTo.Attr> searchAttrs = productAttrValueEntities.stream().filter(item -> return searchAttrIdsSet.contains(item.getAttrId()); ).map(item -> SpuUpTo.Attr attr = new SpuUpTo.Attr(); BeanUtils.copyProperties(item, attr); return attr; ).collect(Collectors.toList()); //3.查出所有的sku List<SkuInfoEntity> skuInfoEntities = skuInfoService.list(new QueryWrapper<SkuInfoEntity>().eq("spu_id", spuId)); //4.准备所有sku的库存信息:传递skuId列表获取对应的库存信息,使用map封装。(远程调用库存服务) List以上是关于谷粒商城高级篇商品服务 & 商品上架的主要内容,如果未能解决你的问题,请参考以下文章