商品上架:构造基本数据
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信息
List skus = 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信息
List skus = 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的那块