发布商品
调试会员等级接口
启动会员微服务,添加网关,添加前端页面…
添加如下会员:
获取分类关联的品牌
controller
/** * 1.获取分类关联的品牌 * /product/categorybrandrelation/brands/list */ @GetMapping("/brands/list") public R relationBrandList(@RequestParam(value = "catId", required = true) Long catId) { List<BrandEntity> vos = categoryBrandRelationService.getBrandsByCatId(catId); //品牌对象集合在进行筛选,赋予品牌对象id和name,返回封装的vo给前端 List<BrandVo> collect = vos.stream().map(item -> { BrandVo brandVo = new BrandVo(); brandVo.setBrandId(item.getBrandId()); brandVo.setBrandName(item.getName()); return brandVo; }).collect(Collectors.toList()); return R.ok().put("data",collect); }
service
@Override public List<BrandEntity> getBrandsByCatId(Long catId) { //获得CategoryBrandRelationEntity集合对象 List<CategoryBrandRelationEntity> catelogId = relationDao.selectList(new QueryWrapper<CategoryBrandRelationEntity>().eq("catelog_id", catId)); //获得所有集合对象中brandid,通过brandService查询所有品牌,封装成品牌对象集合 List<BrandEntity> collect = catelogId.stream().map(item -> { Long brandId = item.getBrandId(); BrandEntity entity = brandService.getById(brandId); return entity; }).collect(Collectors.toList()); //返回品牌对象集合 return collect; }
测试
开发规范
- Controller:处理请求,接受和校验数据
- Service接受controlLer传来的数据,进行业务处理
- Controller接受service处理完的数据,封装页面指定的vo
获取分类下所有分组&关联属性
接口功能如下
也就是说当我们选择手机分类时,那就查出手机相关的分组信息,并查出每个分组相应属性信息
vo
@Data public class AttrGroupWithAttrsVo { /** * 分组id */ @TableId private Long attrGroupId; /** * 组名 */ private String attrGroupName; /** * 排序 */ private Integer sort; /** * 描述 */ private String descript; /** * 组图标 */ private String icon; /** * 所属分类id */ private Long catelogId; private List<AttrEntity> attrs; }
controller
/** * 7.获取分类下所有分组&关联属性 * /product/attrgroup/{catelogId}/withattr */ @GetMapping("/{catelogId}/withattr") public R getAttrGroupWithAttrs(@PathVariable("catelogId") Long catelogId) { List<AttrGroupWithAttrsVo> vos = attrGroupService.getAttrGroupWithAttrsByCatelogId(catelogId); return R.ok().put("data",vos); }
service
vo的重要性:
vo(value object)当相应数据需要自定义时,用vo是最好的选择,不需要对实体类字段进行修改
/** * 获取分类下的所有分组及属性 * @param catelogId * @return */ @Override public List<AttrGroupWithAttrsVo> getAttrGroupWithAttrsByCatelogId(Long catelogId) { /** 1.获取分类下的所有分组,封装成集合 * 分类和组的关系在pms_group表中,所以(where catelog_id = ?)即可查出分类对应的组 * 由于这是mp,它会得出所有的这种关系,并把结果封装成集合 */ List<AttrGroupEntity> list = this.list(new QueryWrapper<AttrGroupEntity>().eq("catelog_id", catelogId)); /** 2.获得分组下的属性 * 要第三张关联表,直接调用关联表的service即查询分组对应的属性id * 获得属性id在去调用属性表的service即可查询属性名 * 以上两步前面已经写好逻辑了直接调用即可attrService.getRelationAttr(groupId) */ List<AttrGroupWithAttrsVo> collect = list.stream().map((item) -> { AttrGroupWithAttrsVo attrGroupWithAttrsVo = new AttrGroupWithAttrsVo(); BeanUtils.copyProperties(item, attrGroupWithAttrsVo); List<AttrEntity> attrs = attrService.getRelationAttr(attrGroupWithAttrsVo.getAttrGroupId()); if (attrs != null) { attrGroupWithAttrsVo.setAttrs(attrs); } return attrGroupWithAttrsVo; }).filter((attrvo) -> { return attrvo.getAttrs() != null && attrvo.getAttrs().size() > 0; }).collect(Collectors.toList()); return collect; }
测试
商品新增vo抽取
设置完属性,点击保存之后取消保存,复制控制台输出
[在线JSON字符串转Java实体类(JavaBean、Entity)-BeJSON.com](https://www.bejson.com/json2javapojo/new/)
直接解析json数据封装成实体类
这里我简单截取一个主要的Vo
此Vo包括每个步骤所携带的数据,有的是单个字段有的是一个集合
逻辑不难,难点是要理清逻辑,注意细节!
@Data public class SpuSaveVo { @NotEmpty(groups = {AddGroup.class}) private String spuName; private String spuDescription; @NotEmpty(groups = {AddGroup.class}) private Long catalogId; @NotEmpty(groups = {AddGroup.class}) private Long brandId; private double weight; private int publishStatus; private List<String> decript; private List<String> images; private Bounds bounds; @NotEmpty(groups = {AddGroup.class}) private List<BaseAttrs> baseAttrs; @NotEmpty(groups = {AddGroup.class}) private List<Skus> skus; }
商品新增业务流程分析
逻辑很简单那,就是把数据保存到多张表中
因为这个Vo收集的数据很多,包括每个步骤你所选择的数据
1.保存spu基本信息 pms_spu_info
因为所有传来的信息都在vo里,所以我们把信息拷贝到对应的实体类中,如果vo没有的那就可以自己赋值
表结构如下:
这里的infoEntity.setCreateTime(new Date());infoEntity.setUpdateTime(new Date());是因为前端传入的是没有这两个字段的,我们自己赋值即可
SpuInfoEntity infoEntity = new SpuInfoEntity(); BeanUtils.copyProperties(vo, infoEntity); infoEntity.setCreateTime(new Date()); infoEntity.setUpdateTime(new Date()); this.saveBaseInfo(infoEntity);
2.保存spu的描述图片 pms_spu_info_desc
保存哪个数据到哪个表,就注入那个service
String.join()的作用是把集合中的元素通过","分割形成一个一个的字符串
List<String> decript = vo.getDecript(); SpuInfoDescEntity descEntity = new SpuInfoDescEntity(); descEntity.setSpuId(infoEntity.getId()); descEntity.setDecript(String.join(",", decript)); spuInfoDescService.saveSpuInfoDesc(descEntity);
3.保存spu的图片集 pms_spu_images
从vo中获取所有图片集合
调用图片service进行保存,保存只需要两个点
图片id和url地址,传入对象即可
List<String> images = vo.getImages(); imagesService.saveImages(infoEntity.getId(), images);
4.保存spu的规格参数 pms_product_attr_value
从vo中获取所有规格参数集合
对规格参数集合进行遍历,设置每项的属性
List<BaseAttrs> baseAttrs = vo.getBaseAttrs(); List<ProductAttrValueEntity> collect = baseAttrs.stream().map((attr) -> { ProductAttrValueEntity valueEntity = new ProductAttrValueEntity(); valueEntity.setAttrId(attr.getAttrId()); AttrEntity id = attrService.getById(attr.getAttrId()); valueEntity.setAttrName(id.getAttrName()); valueEntity.setAttrValue(attr.getAttrValues()); valueEntity.setQuickShow(attr.getShowDesc()); valueEntity.setSpuId(infoEntity.getId()); return valueEntity; }).collect(Collectors.toList()); attrValueService.saveProductAttr(collect);
5.保存spu的积分信息 mall_sms -> sms_spu_bounds
Bounds bounds = vo.getBounds(); SpuBoundTo spuBoundTo = new SpuBoundTo(); BeanUtils.copyProperties(bounds, spuBoundTo); spuBoundTo.setSpuId(infoEntity.getId()); R r0 = couponFeignService.saveSpuBounds(spuBoundTo); if (r0.getCode() != 0) { log.error("远程保存spu积分信息异常"); } couponFeignService.saveSpuBounds(spuBoundTo);
6.保存当前spu对应的所有sku信息;
//6.1sku的基本信息;pms_sku_info List<Skus> skus = vo.getSkus(); if (skus != null && skus.size() > 0) { skus.forEach(item -> { String defalutImg = ""; for (Images image : item.getImages()) { if (image.getDefaultImg() == 1) { defalutImg = image.getImgUrl(); } } SkuInfoEntity skuInfoEntity = new SkuInfoEntity(); BeanUtils.copyProperties(item, skuInfoEntity); //添加vo中没有的信息 skuInfoEntity.setBrandId(infoEntity.getBrandId()); skuInfoEntity.setCatalogId(infoEntity.getCatalogId()); skuInfoEntity.setSaleCount(0L); skuInfoEntity.setSpuId(infoEntity.getId()); skuInfoEntity.setSkuDefaultImg(defalutImg); skuInfoService.saveSkuInfo(skuInfoEntity); //6.2sku图片信息;pms_sku_images //没有图片路径的无需保存 Long skuId = skuInfoEntity.getSkuId(); List<SkuImagesEntity> imageEntities = item.getImages().stream().map(img -> { SkuImagesEntity skuImagesEntity = new SkuImagesEntity(); skuImagesEntity.setSkuId(skuId); skuImagesEntity.setImgUrl(img.getImgUrl()); skuImagesEntity.setDefaultImg(img.getDefaultImg()); return skuImagesEntity; }).filter(entity -> { return !StringUtils.isEmpty(entity.getImgUrl()); }).collect(Collectors.toList()); skuImagesService.saveBatch(imageEntities); //6.3sku的销售属性;pms_sku_sale_attr_value List<Attr> attr = item.getAttr(); List<SkuSaleAttrValueEntity> skuSaleAttrValueEntities = attr.stream().map(a -> { SkuSaleAttrValueEntity attrValueEntity = new SkuSaleAttrValueEntity(); BeanUtils.copyProperties(a, attrValueEntity); attrValueEntity.setSkuId(skuId); return attrValueEntity; }).collect(Collectors.toList()); skuSaleAttrValueService.saveBatch(skuSaleAttrValueEntities); //6.4sku的优惠满减信息(跨服务); SkuReductionTo skuReductionTo = new SkuReductionTo(); BeanUtils.copyProperties(item, skuReductionTo); skuReductionTo.setSkuId(skuId); if (skuReductionTo.getFullCount() > 0 || skuReductionTo.getFullPrice().compareTo(new BigDecimal("0")) == 1) { R r1 = couponFeignService.saveSkuReduction(skuReductionTo); if (r1.getCode() != 0) { log.error("远程保存spu积分信息异常"); } } }); }
测试
检索功能
也就是多条件分页查询,很常见的功能!
spu检索
controller
/** * 列表 */ @RequestMapping("/list") public R list(@RequestParam Map<String, Object> params){ PageUtils page = spuInfoService.queryPageByCondition(params); return R.ok().put("page", page); }
service
@Override public PageUtils queryPageByCondition(Map<String, Object> params) { QueryWrapper<SpuInfoEntity> queryWrapper = new QueryWrapper<>(); String key = (String) params.get("key"); if (!StringUtils.isEmpty(key)) { //等价sql: status=1 and (id=1 or spu_name like xxx) queryWrapper.and((w) -> { w.eq("id", key).or().like("spu_name", key); }); } String status = (String) params.get("status"); if (!StringUtils.isEmpty(status)) { queryWrapper.eq("publish_status", status); } String brandId = (String) params.get("brandId"); if (!StringUtils.isEmpty(brandId) && !"0".equalsIgnoreCase(brandId)) { queryWrapper.eq("brand_id", brandId); } String catelogId = (String) params.get("catelogId"); if (!StringUtils.isEmpty(catelogId) && !"0".equalsIgnoreCase(catelogId)) { queryWrapper.eq("catalog_id", catelogId); } IPage<SpuInfoEntity> page = this.page( new Query<SpuInfoEntity>().getPage(params), queryWrapper ); return new PageUtils(page); }
sku检索
controller
/** * 列表 */ @RequestMapping("/list") public R list(@RequestParam Map<String, Object> params){ PageUtils page = skuInfoService.queryPageByParams(params); return R.ok().put("page", page); }
service
@Override public PageUtils queryPageByParams(Map<String, Object> params) { QueryWrapper<SkuInfoEntity> queryWrapper = new QueryWrapper<>(); String key = (String) params.get("key"); if (!StringUtils.isEmpty(key)) { queryWrapper.and((w) -> { w.eq("sku_id", key).or().like("sku_name", key); }); } String catelogId = (String) params.get("catelogId"); if (!StringUtils.isEmpty(catelogId) && !"0".equalsIgnoreCase(catelogId)) { queryWrapper.eq("catalog_id", catelogId); } String brandId = (String) params.get("brandId"); if (!StringUtils.isEmpty(brandId) && !"0".equalsIgnoreCase(brandId)) { queryWrapper.eq("brand_id", brandId); } String max = (String) params.get("max"); if (!StringUtils.isEmpty(max)) { try { BigDecimal bigDecimal = new BigDecimal(max); if (bigDecimal.compareTo(new BigDecimal("0")) == 1) { queryWrapper.le("price", max); } } catch (Exception e) { } } String min = (String) params.get("min"); if (!StringUtils.isEmpty(min)) { queryWrapper.ge("price", min); } IPage<SkuInfoEntity> page = this.page( new Query<SkuInfoEntity>().getPage(params), queryWrapper ); return new PageUtils((page)); }