一文了解商品详情页与库存的核心代码和设计说明

后台-系统设置-扩展变量-手机广告位-内容正文顶部

一、商品详情页

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);

  //参数

  Listlist=this.goodsParamsManager.queryGoodsParams(goods.getCategoryId(),goodsId);

  detail.setParamList(list);

  //相册

  ListgalleryList=goodsGalleryManager.list(goodsId);

  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){

  ListskuList=goods.getSkuList();

  //由缓存中获取sku的可用库存和实际库存

  //此操作为批量操作,因为是高频操作,要尽量减少和redis的交互次数

  Listkeys=createKeys(skuList);

  //将商品的可用库存和实际库存一起读

  keys.add(StockCacheKeyUtil.goodsEnableKey(goods.getGoodsId()));

  keys.add(StockCacheKeyUtil.goodsActualKey(goods.getGoodsId()));

  ListquantityList=stringRedisTemplate.opsForValue().multiGet(keys);

  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){

  Mapmap=goodsQuantityManager.fillCacheFromDB(skuVO.getSkuId());

  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整理的关于商品详情页与库存设计的详细内容,欢迎阅读参考。

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。

后台-系统设置-扩展变量-手机广告位-内容正文底部
留言与评论(共有 0 条评论)
   
验证码: