后台-系统设置-扩展变量-手机广告位-内容正文顶部 |
一、商品详情页
1、设计说明
商品详情页分为服务器端渲染和前端异步渲染部分,服务器端渲染通过静态页功能静态化展示
服务器端渲染:商品名称、商品价格、分类名称、规格参数、商品详情、商品相册、商品好评率、店铺的信息等
浏览器异步渲染:商品的库存,商品的规格,商品的参与的活动、商品评论、商品咨询、销售记录等
2、表结构设计
商品相册表(es_goods_gallery)
存储商品图片的链接地址
交易快照表(es_goods_snapshot)
订单生成时,把下单的商品数据写入此表,留作凭证。
3、核心代码展示
静态部分
@ApiOperation(value="浏览商品的详情,静态部分使用")
@ApiImplicitParam(name="goods_id",value="分类id,顶级为0",required=true,dataType="long",paramType="path")
@GetMapping("/{goods_id}")
publicGoodsShowDetailgetGoodsDetail(@PathVariable("goods_id")LonggoodsId){
GoodsDOgoods=goodsQueryManager.getModel(goodsId);
GoodsShowDetaildetail=newGoodsShowDetail();
if(goods==null){
thrownewResourceNotFoundException("不存在此商品");
}
BeanUtils.copyProperties(goods,detail);
IntegergoodsOff=0;
//商品不存在,直接返回
if(goods==null){
detail.setGoodsOff(goodsOff);
returndetail;
}
//分类
CategoryDOcategory=categoryManager.getModel(goods.getCategoryId());
detail.setCategoryName(category==null?"":category.getName());
//上架状态
if(goods.getMarketEnable()==1){
goodsOff=1;
}
detail.setGoodsOff(goodsOff);
//参数
List
detail.setParamList(list);
//相册
List
detail.setGalleryList(galleryList);
//商品好平率
detail.setGrade(goodsQueryManager.getGoodsGrade(goodsId));
returndetail;
}
动态部分
@ApiOperation(value="获取sku信息,商品详情页动态部分")
@ApiImplicitParam(name="goods_id",value="商品id",required=true,dataType="long",paramType="path")
@GetMapping("/{goods_id}/skus")
publicList<GoodsSkuVO>getGoodsSkus(@PathVariable("goods_id")LonggoodsId){
CacheGoodsgoods=goodsQueryManager.getFromCache(goodsId);
returngoods.getSkuList();
}
@Override
CacheGoodsgoods=(CacheGoods)cache.get(CachePrefix.GOODS.getPrefix()+goodsId);
if(goods==null){
GoodsDOgoodsDB=this.getModel(goodsId);
if(goodsDB==null){
thrownewServiceException(GoodsErrorCode.E301.code(),"该商品已被彻底删除");
}
//GoodsVo的对象返回,GoodsVo中的skuList是要必须填充好的
List<GoodsSkuVO>skuList=goodsSkuManager.listByGoodsId(goodsId);
//类型转换
goods=newCacheGoods();
BeanUtils.copyProperties(goodsDB,goods);
goods.setSkuList(skuList);
//填充库存数据
fillStock(goods);
cache.put(CachePrefix.GOODS.getPrefix()+goodsId,goods);
returngoods;
}else{
//填充库存数据
fillStock(goods);
}
二、库存设计
1、设计思路
添加库存:goods表的库存字段,人员不能进行编辑,而是编辑对应的SKU库存,再通过SKU总库存,写入goods表的库存字段
扣减库存:扣减reids的库存,一定状态后统一同步到数据库。
2、实现方法
采用lua脚本执行redis中的库存扣减
数据库的更新采用非时时同步,而是建立了一个缓冲池,当达到一定条件时再同步数据库。
这样条件有:缓冲区大小,缓冲次数,缓冲时间
上述条件在配置中心可以配置,如果没有配置采用${@linkUpdatePool}默认值
在配置项说明:
缓冲区大小:javashop.pool.stock.max-pool-size
缓冲次数:javashop.pool.stock.max-update-time
缓冲时间(秒数):javashop.pool.stock.max-lazy-second
3、核心代码展示
GoodsQuantityVO:
//商品ID
privateLonggoodsId;
//skuID
privateLongskuId;
//库存值
privateIntegerquantity;
//库存类型actual:实际的库存,包含了待发货的
enable:可以售的库存,不包含待发货的
privateQuantityTypequantityType;
GoodsQueryManagerImpl
/**
*为商品填充库存信息
*库存的信息存储在单独的缓存key中
*由缓存中读取出所有sku的库存,并分别为goods.skuList中的sku设置库存,以保证库存的时时正确性
*同时还会将所有的sku库存累加设置为商品的库存
*
*@paramgoods
*/
protectedvoid(CacheGoodsgoods){
List
//由缓存中获取sku的可用库存和实际库存
//此操作为批量操作,因为是高频操作,要尽量减少和redis的交互次数
Listkeys=createKeys(skuList);
//将商品的可用库存和实际库存一起读
keys.add(StockCacheKeyUtil.goodsEnableKey(goods.getGoodsId()));
keys.add(StockCacheKeyUtil.goodsActualKey(goods.getGoodsId()));
List
intenableTotal=0;
intactualTotal=0;
inti=0;
for(GoodsSkuVOskuVO:skuList){
//第一个是可用库存
Integerenable=StringUtil.toInt(quantityList.get(i),null);
i++;
//第二个是真实库存
Integeractual=StringUtil.toInt(quantityList.get(i),null);
//缓存被击穿,由数据库中读取
if(enable==null||actual==null){
Map
enable=map.get("enable_quantity");
actual=map.get("quantity");
//重置缓存中的库存
stringRedisTemplate.opsForValue().set(StockCacheKeyUtil.skuEnableKey(skuVO.getSkuId()),""+enable);
stringRedisTemplate.opsForValue().set(StockCacheKeyUtil.skuActualKey(skuVO.getSkuId()),""+actual);
}
skuVO.setEnableQuantity(enable);
skuVO.setQuantity(actual);
if(enable==null){
enable=0;
}
if(actual==null){
actual=0;
}
//累计商品的库存
enableTotal+=enable;
actualTotal+=actual;
i++;
}
//设置商品的库存
goods.setEnableQuantity(enableTotal);
goods.setQuantity(actualTotal);
//读取缓存中商品的库存,看是否被击穿了
//第一个是可用库存
IntegergoodsEnable=StringUtil.toInt(quantityList.get(i),null);
i++;
//第二个是真实库存
IntegergoodsActual=StringUtil.toInt(quantityList.get(i),null);
//商品的库存被击穿了
if(goodsEnable==null||goodsActual==null){
//重置缓存中的库存
stringRedisTemplate.opsForValue().set(StockCacheKeyUtil.goodsEnableKey(goods.getGoodsId()),""+enableTotal);
stringRedisTemplate.opsForValue().set(StockCacheKeyUtil.goodsActualKey(goods.getGoodsId()),""+actualTotal);
}
}
上述就是易族智汇javashop整理的关于商品详情页与库存设计的详细内容,欢迎阅读参考。
郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。
郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。