100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > 【谷粒商城高级篇】商品服务 商品上架

【谷粒商城高级篇】商品服务 商品上架

时间:2019-02-01 15:33:45

相关推荐

【谷粒商城高级篇】商品服务  商品上架

谷粒商城笔记合集

二、商品服务 & 商品上架

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_skuWHERE sku_id = 1

组装数据 设置 SkuEsModel

发送给 es 保存

2.3.1 公共服务⚠️

创建用于传输sku库存信息的TO,用于商品上架过程中远程获取库存信息:cn/lzwei/common/to/SkuHasStockTo.java

@Datapublic 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

@Datapublic 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;@Datapublic 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,"商品上架异常");}

新增商品状态的枚举常量类,用于商品上架成功后的状态更新:mon.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

@Datapublic class SkuHasStockVo {private Long skuId;private Boolean hasStock;}

WareSkuController:商品上架远程调用:通过skuId列表获取sku对应的库存信息

@RestController@RequestMapping("ware/waresku")public class WareSkuController {@Autowiredprivate 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对应的库存信息*/@Overridepublic List<SkuHasStockVo> getSkusWareInfoBySkuIds(List<Long> skuIds) {List<SkuHasStockVo> collect = skuIds.stream().map(skuId -> {SkuHasStockVo skuHasStockVo = new SkuHasStockVo();//1.设置skuIdskuHasStockVo.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剩余库存:库存量-锁定库存量

@Mapperpublic 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@Slf4jpublic class ProductSaveController {@ResourceProductSaveService 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")@Slf4jpublic class ProductSaveServiceImpl implements ProductSaveService {@ResourceRestHighLevelClient restHighLevelClient;/*** 保存商品信息*/@Overridepublic 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、设置idindexRequest.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, MON_OPTIONS);boolean b = bulk.hasFailures();//获取上架的skuIdList<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 {@Autowiredprivate 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 {@ResourceProductAttrValueService productAttrValueService;@ResourceAttrService attrService;@ResourceSkuInfoService skuInfoService;@ResourceBrandService brandService;@ResourceCategoryService categoryService;@ResourceWareFeignService wareFeignService;@ResourceSearchFeignService searchFeignService;/*** 商品上架:将所属的sku信息保存到elasticsearch中*/@Transactional@Overridepublic 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.查出所有的skuList<SkuInfoEntity> skuInfoEntities = skuInfoService.list(new QueryWrapper<SkuInfoEntity>().eq("spu_id", spuId));//4.准备所有sku的库存信息:传递skuId列表获取对应的库存信息,使用map封装。(远程调用库存服务)List<Long> skuIds = skuInfoEntities.stream().map(item -> {return item.getSkuId();}).collect(Collectors.toList());Map<Long, Boolean> stockMap=null;try{R r = wareFeignService.getSkusWareInfoBySkuIds(skuIds);TypeReference<List<SkuHasStockTo>> typeReference = new TypeReference<List<SkuHasStockTo>>(){};List<SkuHasStockTo> stocks = r.getData(typeReference);stockMap = stocks.stream().collect(Collectors.toMap(SkuHasStockTo::getSkuId, SkuHasStockTo::getHasStock));}catch (Exception e){log.error("远程调用库存服务失败:{}",e);System.out.println(e.getCause());}//5.遍历所有sku:进行数据封装,封装成TOMap<Long, Boolean> finalStockMap = stockMap;List<SpuUpTo> spuUpTos = skuInfoEntities.stream().map(item -> {SpuUpTo spuUpTo = new SpuUpTo();//5.1、属性对拷BeanUtils.copyProperties(item,spuUpTo);//TODO 商品上架:热点评分设置//5.2、设置价格、图片、热点评分spuUpTo.setSkuPrice(item.getPrice());spuUpTo.setSkuImg(item.getSkuDefaultImg());spuUpTo.setHotScore(0l);//5.3、设置品牌名称、品牌图片spuUpTo.setBrandName(brandInfo.getName());spuUpTo.setBrandImg(brandInfo.getLogo());//5.4、设置分类名spuUpTo.setCatalogName(categoryInfo.getName());spuUpTo.setCatalogId(catalogId);//5.5、设置库存if(finalStockMap ==null){spuUpTo.setHasStock(true);}else {spuUpTo.setHasStock(finalStockMap.get(item.getSkuId()));}//5.6、设置规格参数:attrId、attrName、attrValuespuUpTo.setAttrs(searchAttrs);return spuUpTo;}).collect(Collectors.toList());//5.将封装好的TO传递给 bilimall-search服务,保存到elasticsearch中(远程调用)R r = searchFeignService.productStatusUp(spuUpTos);if(r.getCode()==0){//远程调用成功:修改商品状态为上架baseMapper.updateSpuStatus(spuId, ProductConstant.StatusEnum.SPU_UP.getCode());}else {//远程调用失败//TODO 商品上架:重复调用?接口幂等性?重试机制?}return r;}}

AttrService:获取可用于检索的规格参数

public interface AttrService extends IService<AttrEntity> {/*** 获取可用于检索的规格参数*/List<Long> getSearchAttr(List<Long> productAttrIds);}

AttrServiceImpl:获取可用于检索的规格参数

@Service("attrService")public class AttrServiceImpl extends ServiceImpl<AttrDao, AttrEntity> implements AttrService {/*** 获取可用于检索的规格参数*/@Overridepublic List<Long> getSearchAttr(List<Long> productAttrIds) {List<Long> searchIds=baseMapper.getSearchAttr(productAttrIds);return searchIds;}}

AttrDao.java:获取可用于检索的规格参数

@Mapperpublic interface AttrDao extends BaseMapper<AttrEntity> {/*** 获取可用于检索的规格参数*/List<Long> getSearchAttr(List<Long> productAttrIds);}

AttrDao.xml:获取可用于检索的规格参数

<mapper namespace="cn.lzwei.bilimall.product.dao.AttrDao"><!-- 获取可用于检索的规格参数 --><select id="getSearchAttr" resultType="java.lang.Long">SELECT attr_id FROM `pms_attr` WHERE search_type=1 And attr_id IN<foreach collection="productAttrIds" item="item" separator="," open="(" close=")">#{item}</foreach></select></mapper>

创建库存服务的远程调用接口:cn/lzwei/bilimall/product/feign/WareFeignService.java

@FeignClient(name = "bilimall-ware")public interface WareFeignService {/*** 商品上架远程调用:通过skuId列表获取sku对应的库存信息*/@PostMapping("/ware/waresku/getSkusWareInfoBySkuIds")R getSkusWareInfoBySkuIds(@RequestBody List<Long> skuIds);}

创建索引服务的远程调用接口:cn/lzwei/bilimall/product/feign/SearchFeignService.java

@FeignClient("bilimall-search")public interface SearchFeignService {/*** 保存商品信息*/@PostMapping("//search/save/product")R productStatusUp(@RequestBody List<SpuUpTo> spuUpTo);}

SpuInfoDao.java:上架成功修改商品状态为上架

@Mapperpublic interface SpuInfoDao extends BaseMapper<SpuInfoEntity> {//远程调用成功:修改商品状态为上架void updateSpuStatus(@Param("spuId") Long spuId, @Param("code") Integer code);}

SpuInfoDao.xml:上架成功修改商品状态为上架

<mapper namespace="cn.lzwei.bilimall.product.dao.SpuInfoDao"><update id="updateSpuStatus">UPDATE `pms_spu_info` SET publish_status=#{code},update_time=NOW() WHERE id=#{spuId}</update></mapper>

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。