商品上架:构造基本数据
package com.atguigu.common.to.es; import lombok.Data; import java.io.Serializable; import java.math.BigDecimal; import java.util.List; /** *Title: SkuEsModel
* Description: * "mappings": { * "properties": { * "skuId":{ * "type": "long" * }, * "spuId":{ * "type": "keyword" * }, * "skuTitle":{ * "type": "text", * "analyzer": "ik_smart" * }, * "skuPrice":{ * "type": "keyword" * }, * "skuImg":{ * "type": "keyword", * "index": false, * "doc_values": false * }, * "saleCount":{ * "type": "long" * }, * "hasStock":{ * "type": "boolean" * }, * "hotScore":{ * "type": "long" * }, * "brandId":{ * "type": "long" * }, * "catalogId":{ * "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" * } * } * } * } * } * date:2020/6/8 18:52 */ @Data public class SkuEsModel implements Serializable { 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 Listattrs; /** * 检索属性 */ @Data public static class Attrs implements Serializable{ private Long attrId; private String attrName; private String attrValue; } }
讲道理,这个应该放到product服务和search服务中,这里放到了common服务中。
再次理清 skuspu:
===================================
/** * 不一样的属性:skuPrice、skuImg、hasStock、hotScore、 * brandName、brandImg、catalogName、attrs * * @param spuId */ @Override public void up(Long spuId) { // 1 组装数据 查出当前spuId对应的所有sku信息 Listskus = skuInfoService.getSkusBySpuId(spuId); // TODO 4. 查询当前 SKU的所有 可以被用来检索的规格属性===这些规格属性是按照spu来的,所以放到外面查一遍即可 // 2 封装每个sku的信息 List uoProducts = skus.stream().map((x) -> { SkuEsModel esModel = new SkuEsModel(); //一样的属性: BeanUtils.copyProperties(x,esModel);//这个是spring的类 把当前遍历的sku拷贝到esModel中 //不一样的属性:skuPrice、skuImg、hasStock、hotScore、brandName、brandImg、catalogName、attrs //skuPrice、skuImg esModel.setSkuPrice(x.getPrice()); esModel.setSkuImg(x.getSkuDefaultImg()); // TODO 1. hasStock发送远程调用,查询是否有库存 // TODO 2. hotScore 热度评分。0,后面可以扩展 // TODO 3. brandName brandImg catalogName 查询品牌名字和分类名字,以及品牌图片 BrandEntity brandEntity = brandService.getById(esModel.getBrandId()); esModel.setBrandName(brandEntity.getName()); esModel.setBrandImg(brandEntity.getLogo()); CategoryEntity categoryEntity = categoryService.getById(esModel.getCatalogId()); esModel.setCatalogName(categoryEntity.getName()); return esModel; }).collect(Collectors.toList()); //TODO 5. 将数据发送给ES进行保存,要用search服务来做,不能直接用product服务来做。 }
内容待完成,今天先休息。22:52:51
===============
今天1月24日 22:16:25
/** * 不一样的属性:skuPrice、skuImg、hasStock、hotScore、 * brandName、brandImg、catalogName、attrs * * @param spuId */ @Override public void up(Long spuId) { // 1 组装数据 查出当前spuId对应的所有sku信息 Listskus = skuInfoService.getSkusBySpuId(spuId); // TODO 4. 查询当前 SKU的所有 可以被用来检索的规格属性===这些规格属性是按照spu来的,所以放到外面查一遍即可 List baseAttrs = productAttrValueService.baseAttrListForSpu(spuId);//先得到ProductAttrValueEntity List attrIds = baseAttrs.stream().map((x) -> x.getAttrId()).collect(Collectors.toList());//收集出所有的ID //然后根据attrId 在 attr表中查询,找出search_type==1的记录。也就是可以检索的记录 List searchAttrIds = attrService.selectSearchAttrIds(attrIds); Set idSet = new HashSet<>(searchAttrIds);// 这个时候还只是得到了 符合条件的ID,但是我们最终要的是ProductAttrValueEntity,所以要在基础的过滤一下 List attrsList = baseAttrs.stream() //注意这里是用Attrs 封装的,这样就可以直接放到esModel中了 .filter((x) -> { return idSet.contains(x.getAttrId()); }) .map((x) -> { SkuEsModel.Attrs attr = new SkuEsModel.Attrs(); BeanUtils.copyProperties(x, attr); return attr; }).collect(Collectors.toList()); // TODO 1. hasStock发送远程调用,查询是否有库存 //=============注意这里是远程调用,可能由于网络波动这里会出现异常导致后面都不能执行 Map stockMap = null; try { List skuIds = skus.stream().map((sku) -> sku.getSkuId()).collect(Collectors.toList()); R hasStock = wareFeignService.getSkuHasStock(skuIds); List stockVos = (List ) hasStock.get("data"); // skuId 对应 是否有库存 stockMap = stockVos.stream() .collect(Collectors.toMap( (x) -> x.getSkuId(), (x) -> x.getHasStock() )); log.warn("服务调用成功" + hasStock); } catch (Exception e) { log.error("库存服务调用失败: 原因{}", e); } // 2 封装每个sku的信息 Map finalStockMap = stockMap; List uoProducts = skus.stream().map((x) -> { SkuEsModel esModel = new SkuEsModel(); //一样的属性: BeanUtils.copyProperties(x, esModel);//这个是spring的类 把当前遍历的sku拷贝到esModel中 //不一样的属性:skuPrice、skuImg、hasStock、hotScore、brandName、brandImg、catalogName、attrs //skuPrice、skuImg esModel.setSkuPrice(x.getPrice()); esModel.setSkuImg(x.getSkuDefaultImg()); //设置库存 if (finalStockMap == null) { esModel.setHasStock(true); } else { esModel.setHasStock(finalStockMap.get(x.getSkuId())); } // TODO 2. hotScore 热度评分。0,后面可以扩展 esModel.setHotScore(0L); // TODO 3. brandName brandImg catalogName 查询品牌名字和分类名字,以及品牌图片 BrandEntity brandEntity = brandService.getById(esModel.getBrandId()); esModel.setBrandName(brandEntity.getName()); esModel.setBrandImg(brandEntity.getLogo()); CategoryEntity categoryEntity = categoryService.getById(esModel.getCatalogId()); esModel.setCatalogName(categoryEntity.getName()); //设置检索属性 esModel.setAttrs(attrsList); return esModel; }).collect(Collectors.toList()); //TODO 5. 将数据发送给ES进行保存,要用search服务来做,不能直接用product服务来做。 }
还差一个用search服务发给 ES 的步骤。
上面远程调用ware服务:
在ware服务中加一个 controller方法
//查询SKU是否有库存 //@RequestBody 这个注解就是说,将请求体里面的JSON数据转换为 这个List @PostMapping("/hasstock") public R getSkuHasStock(@RequestBody ListskuIds){ //返回的话,只需返回 sku_id 和 库存量 就行了。所以封装VO List stockVos = wareSkuService.getSkusStock(skuIds); return R.ok().put("data",stockVos); }
然后service遍历skuids ,对于每个skuid查询数据库看有没有库存:
@Override public ListgetSkusStock(List skuIds) { return skuIds.stream() .map((skuId) -> { SkuHasStockVo skuHasStockVo = new SkuHasStockVo(); //查询数据库 long count = baseMapper.getSkusStock(skuId); skuHasStockVo.setSkuId(skuId); skuHasStockVo.setHasStock(count>0); return skuHasStockVo; }).collect(Collectors.toList()); }
//签名上只有一个参数,写什么都可以,但是多个参数就要 @Param 注解。 long getSkusStock(Long skuId);
然后product服务进行远程调用
package com.atguigu.gulimall.product.feign; import com.atguigu.common.utils.R; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import java.util.List; @FeignClient("gulimall-ware") public interface WareFeignService { /** * 视频中说这个返回值有问题,我感觉可以,直接取data里面的数据一样的,不知道为什么视频中提出了三种方案。。 * 1. R 设计的时候加上泛型 * 2. 直接返回我们需要的结果 * 3. 自己封装解析结果----给R类提供方法返回指定数据。 */ @PostMapping("/ware/waresku/hasstock") R getSkuHasStock(@RequestBody ListSkuIds); }
视频把这个返回设计为了R《T》 泛型的形式,后来我想了一下,可能原因就是,写ware服务的人提供返回的类型指定好,然后调用的人不用管返回的类型在强转,直接用ware服务提供的返回类型。
不知道理解的对不对。
总体看上去业务也不算复杂,不过比我之前写的东西还是复杂一些。待会写ES的那块