畅购04——商品管理(分布式ID)

    科技2023-12-24  102

    电商项目——CG

    为何使用分布式ID项目中如何使用分布式ID搞清SPU和SKU的区别商品的CRUD增加商品根据id查询商品修改商品审核商品商品上下架删除商品全局异常处理

    为何使用分布式ID

    我们学过UUID是唯一的,但是它是字符串,查询效率低。无法保证递增的趋势,不可读。也可用Redis来生成ID。这主要依赖于Redis是单线程的,所以也可以用生成全局唯一的ID。可以用Redis的原子操作 INCR和INCRBY来实现,但是网络传输会造成性能下降。而雪花算法(snowflake)的其核心思想是:使用前41bit作为毫秒数,中间10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID),后12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 4096 个 ID),最前还有一个符号位,永远是0(二进制1为负数)。几乎完美解决了上述的问题。

    项目中如何使用分布式ID

    首先引入工具包IdWorker.javachanggou_service_goods中yml配置:这两值只能在0~31之间 workerId: 0 datacenterId: 0 在启动类配置一个idWorker的Bean,以@Value将两个属性注进来。

    搞清SPU和SKU的区别

    概念 SPU:一个统称 SKU:对SPU的细化,比如有颜色,内存大小等等就搞一个SKU不行吗? 答案是:不行,因为对于单个商品(如小米10)的详情,图片,友情链接是一样的。SPU更加便于维护。

    商品的CRUD

    增加商品

    商品Goods由spu和sku组成,所以在…-api中先创建Goods实体类spu业务层新增方法add(Goods goods),先存spu,再存sku。具体逻辑: - 生成分布式ID,重新封装spu(审核状态,删除状态,上架状态全为0),再调用方法spuMapper.insertSelective(spu)进行保存。 - 存sku的时候注意两点,第一:分类与品牌的关联,如未建立则需在tb_category_brand添加数据,方便数据的维护。第二:skuList中拿到的spec是个json字符串,需要将其拿出来转成map取value的值再与name组合生成最终的name。再重新封装sku,向表中添加数据。sku所需数据如下: private String sn;//商品条码 private String name;//SKU名称 private Integer price;//价格(分) private Integer num;//库存数量 private Integer alertNum;//库存预警数量 private String image;//商品图片 private String images;//商品图片列表 private Integer weight;//重量(克) private java.util.Date createTime;//创建时间 private java.util.Date updateTime;//更新时间 private String spuId;//SPUID private Integer categoryId;//类目ID private String categoryName;//类目名称 private String brandName;//品牌名称 private String spec;//规格 private Integer saleNum;//销量 private Integer commentNum;//评论数 private String status;//商品状态 1-正常,2-下架,3-删除

    根据id查询商品

    根据id查询spu。封装Example对象,然后根据id查询出所有的skuList。创建Goods对象,将spu和skuList一起放进对象中并返回。

    修改商品

    首先从goods中拿到spu,对spu进行修改根据spu的id删除所有的sku,再重新增加(调用新增方法)

    审核商品

    分析: 先通过id查询到spu,如果spu为空或者删除状态为1,则抛一个系统异常(本篇的最后),否则就将spu的status和isMarketable设为1。代码如下: @Transactional @Override public void audit(String id) { Spu spu = spuMapper.selectByPrimaryKey(id); if (spu==null || "1".equals(spu.getIsDelete())){ throw new BusinessException(new Result(false, StatusCode.ERROR,"无此商品信息或处于删除状态")); } //审核 spu.setStatus("1"); //上架 spu.setIsMarketable("1"); spuMapper.updateByPrimaryKeySelective(spu); }

    商品上下架

    分析: 无论上下架都要先进行判断,根据id查询spu,若spu为空或者处于删除状态,或status为0都不可操作,抛一个系统异常。否则直接更改上架状态,代码简单,不做赘述。

    删除商品

    逻辑删除(可还原) 先做一个判断,未下架商品不能逻辑删除,下架后可直接更改删除状态为1。 还原商品:当status为0或删除状态为0都不可操作,否则直接修改删除状态为0。物理删除 根据id直接删除数据即可。

    全局异常处理

    主要利用了Aop思想,做了异常捕获类,代码如下:

    /** * 统一异常处理类 */ @ControllerAdvice public class BaseExceptionHandler { //BusinessException继承了RuntimeExcption @ExceptionHandler(value = BusinessException.class) @ResponseBody public Result otherError(BusinessException e){ e.printStackTrace(); return e.getResult(); } @ExceptionHandler(value = Exception.class) @ResponseBody public Result error(Exception e){ e.printStackTrace(); return new Result(false, StatusCode.ERROR, "执行出错"); } }
    Processed: 0.017, SQL: 8