功能拆分
- 仓储服务:查询sku是否有库存
- 商品服务:查询出所有允许被检索的规格参数
- 商品服务:调用仓储服务查询sku是否有库存
- 商品服务:查询品牌、分类信息
- 商品服务:准备好保存到Es的所有数据
- 商品服务:调用检索服务将数据保存到Es
- 商品服务:根据保存结果决定是否更新商品状态
- 检索服务:将商品服务传过来的上传数据保存到Es
前言
以下步骤及思路,有部分出入,具体请参考代码,
https://gitee.com/UnityAlvin/gulimall/commits/master
统计提交中,选择日期,2021-6-17,所有与“130-135”有关的提交,以及“style:通用异常字段”这个提交
商品服务
// 1. 通过 spuId 获取 List<SkuInfoEntity>,定义为 skuInfoList
// 2. 查询当前 sku 所有可检索的规格属性
// 2.1 通过 spuId 获取 List<ProductAttrValueEntity> ,定义为 attrValues
// 2.2 stream 流:从 attrValues 中提取出 attrId ,转成集合 attrIds
// 2.3 通过 attrIds ,查询 search_type 为1的 List<Long> searchAttrIds
// 2.4 将 searchAttrIds 转成 Set<Long> attrIdSet
// 2.5 stream 流:attrValues
// 过滤:attrIdSet.contains(attrValue.getAttrId())
// 映射:
// 新建一个 SkuEsModel.Attr 的对象 attr
// 将 attrValue 拷贝 到 attr
// 返回 attr
// 收集:转换成 List<SkuEsModel.Attr> attrs
// 3. 需要调用仓储服务,查询是否有库存:stockOrNot
// 3.1 stream 流:skuInfoList
// 映射:SkuInfoEntity::getSkuId
// 收集:转换成 List<Long> skuIds
// 定义 Map<Long, Boolean> stockMap = null;
// 因为可能会出现远程服务调用失败的情况,所以需要创建 try-catch
// 调用 WareFeignService 查询否有库存,返回R
// stream 流:r.getData(new TypeReference<List<SkuStockTO>>() {})
// 收集:
// toMap(SkuStockTO::getSkuId,SkuStockTO::getStockOrNot))
// 赋值给 stockMap
// 因为 stream 要求用到的局部变量必须是 final 类型的
// 所以需要将 stockMap 赋值给一个新变量 finalStockMap
// 4. stream流:skuInfoList,遍历项skuInfo
// 将 skuInfo 的属性复制到 SkuEsModel,获取到对象 skuEsModel
// 有一些复制不过去的属性,需要手动设置
// 可以直接set:price、skuImg
// 通过brandId、categoryId查询品牌、分类信息设置:brandName、brandImg、categoryName
// attrs:上面已经查出来了
// hotScore:先设置为0
// hasStock:判断finalSkuHasStock是否为空
// 为空,则直接赋值为true,不为空,再根据 skuHasStockMap.get(sku.getSkuId) 设置
// 5. 调用远程服务,进行es保存,返回R
// 判断R.getCode()
// 为true,则根据spuId, 更新商品的状态,值为上架状态的code
公共服务
R
// 添加一个R setData(Object data)方法,里面put("data",data), return this;
// 利用fastjson进行逆转
<T> T getData(TypeReference<T> type){
Object data = get("data");
String s = JSON.toJsSONString(data);
T t = JSON.parseObject(s,type);
return t;
}
// 让仓储服务返回数据的时候,调用R.setData()
TO
SkuHasStockTO
private Long skuId;
private Boolean hasStock;
Exception
BizCodeEnum
PRODUCT_UP_EXCEPTION(11000,"商品上架异常");
Constant
ProductConstant
ProductStatusEnum{
SPU_NEW(0,新建)
SPU_UP(1,商品上架)
SPU_DOWN(2, 商品下架)
}
仓储服务
// 通过 skuIds 获取 List<SkuHasStockVO>
// stream流:遍历skuIds
// 映射:
// new 一个 SkuHasStockVO的对象
// Long count 根据skuId,获取到总库存-锁定库存之后的数量:
// 这个方法需要修改数据库的配置文件、否则会报group_by错误
// select sum(stock-stock_locked) from wms_ware_sku where sku_id = #{skuId}
// 设置skuId、hasStock(count == null ? false : count > 0)
// 返回skuHasStockVO
// 收集:转换成List<SkuHasStockVO> skuHasStockVOs
检索服务
application.yml
server
port: 12000
EsSaveController
// 将商品服务传过来的 List<SkuEsModel> skuEsModels 存入到 es 中
// bool flag = false;
// try
// flag = productSaveService.productStatusUp(skuEsModels);
// catch
// log.error("上架异常{}",e)
// return R.error(商品上架异常的code,商品上架异常的msg);
// 判断 flag
// true ,则返回R.error(商品上架异常的code,商品上架异常的msg);
// false ,则返回R.ok();
EsConstant
// 定义一个商品服务的常量,用来存储 sku 在 es 中的索引
// public static final PRODUCT_INDEX = “product”;
ProductSaveService
// 注入es的远程连接
boolean productStatusUp(List<SkuEsModel> skuEsModels){
// 具体实现
// 1. 操作Kibana建立映射关系
// 2. es批量保存这些数据
// 创建批量保存请求 BulkRequest bulkRequest
// 遍历skuEsModels
// 创建保存索引
// 指定索引id
// 设置Json索引数据
// 为批量保存请求设置数据,bulkRequest.add(Json索引数据)
// 调用es远程连接,执行批量保存请求,返回BulkResponse
// 获取是否保存成功bulkResponse.hasFailures(),定义为flag
// stream 流:bulkResponse.getItems()
// 映射:BulkItemResponse::getId
// 收集:List<String> errors
// 打印 errors
// 返回 flag
}