当前位置:网站首页>谷粒商城10——搜索、商品详情、异步编排
谷粒商城10——搜索、商品详情、异步编排
2022-08-02 03:33:00 【HotRabbit.】
文章目录
六、商城业务-搜索页面
1.页面跳转配置
[root@iZ2ze30iuo2wom5i3mm5qlZ /]# cd /mydata/nginx/conf/conf.d/
[root@iZ2ze30iuo2wom5i3mm5qlZ conf.d]# vi gulimall.conf
以gulimall.com结尾的访问路径 都转到网关去
网关配置:
- id: admin_host_route
uri: lb://gulimall-product
predicates:
- Host=gulimall.com
- id: admin_search_route
uri: lb://gulimall-search
predicates:
- Host=search.gulimall.com
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AV6IJ6eb-1659072942560)(C:\Users\10418\AppData\Roaming\Typora\typora-user-images\image-20220723110710007.png)]
配置search服务页面跳转
@Controller
public class SearchController {
@GetMapping("/list.html")
public String listPage(){
return "list";
}
}
2.封装、编写vo实体类
封装前端检索条件:
keyword=小米&sort=saleCount_desc/asc&hasStock=0/1&skuPrice=400_1900&brandId=1&catalog3Id=1&at trs=1_3G:4G:5G&attrs=2_骁龙845&attrs=4_高清屏
@Data
public class SearchParam {
/** * 页面传递过来的全文匹配关键字 */
private String keyword;
/** * 品牌id,可以多选 */
private List<Long> brandId;
/** * 三级分类id */
private Long catalog3Id;
/** * 排序条件:sort=price/salecount/hotscore_desc/asc */
private String sort;
/** * 是否显示有货 */
private Integer hasStock = 1;
/** * 价格区间查询 */
private String skuPrice;
/** * 按照属性进行筛选 */
private List<String> attrs;
/** * 页码 */
private Integer pageNum = 1;
/** * 原生的所有查询条件 */
private String _queryString;
}
封装返回数据:
@Data
public class SearchResponse {
/** * 所有商品信息 */
private List<SkuModel> products;
/** * 分页信息 */
private Integer pageNum;//当前页码
private Long total;//总记录数
private Long totalPage;//总页码
/** * 当前查询到的结果,所以涉及到的品牌 */
private List<BrandVo> brands;
/** *当前查询到的结果,所以涉及到的分类 */
private List<CatalogVo> catalogs;
/** * 当前查询到的结果,所以涉及到的属性 */
private List<AttrVo> attrs;
@Data
public static class BrandVo{
private Long brandId;
private String brandName;
private String brandImg;
}
@Data
public static class CatalogVo{
private Long catalogId;
private String catalogName;
}
@Data
public static class AttrVo{
private Long attrId;
private String attrName;
private List<String> attrValue;
}
}
3.ES 编写 DSL
//数据迁移
PUT gulimall_product
{
"mappings": {
"properties": {
"skuId": {
"type": "long"
},
"spuId": {
"type": "keyword"
},
"skuTitle": {
"type": "text",
"analyzer": "ik_smart"
},
"skuPrice": {
"type": "keyword"
},
"skuImg": {
"type": "keyword"
},
"saleCount": {
"type": "long"
},
"hasStock": {
"type": "boolean"
},
"hotScore": {
"type": "long"
},
"brandId": {
"type": "long"
},
"catelogId": {
"type": "long"
},
"brandName": {
"type": "keyword"
},
"brandImg": {
"type": "keyword"
},
"catelogName": {
"type": "keyword"
},
"attrs": {
"type": "nested",
"properties": {
"attrId": {
"type": "long"
},
"attrName": {
"type": "keyword"
},
"attrValue": {
"type": "keyword"
}
}
}
}
}
}
GET gulimall_product/_mapping
POST _reindex
{
"source": {
"index": "product"
},
"dest": {
"index":"gulimall_product"
}
}
//查询条件
GET gulimall_product/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"skuTitle": "华为"
}
}
],
"filter": [
{
"term": {
"catelogId": "225"
}
},
{
"terms": {
"brandId": [
"9"
]
}
},
{
"term": {
"hasStock": "true"
}
},
{
"range": {
"skuPrice": {
"gte": 1000,
"lte": 7000
}
}
},
{
"nested": {
"path": "attrs",
"query": {
"bool": {
"must": [
{
"term": {
"attrs.attrId": {
"value": "15"
}
}
}
]
}
}
}
}
]
}
},
"sort": [
{
"skuPrice": {
"order": "desc"
}
}
],
"from": 0,
"size": 5,
"highlight": {
"fields": {
"skuTitle": {
}
},
"pre_tags": "<b style='color:red'>",
"post_tags": "</b>"
},
"aggs": {
"brandAgg": {
"terms": {
"field": "brandId",
"size": 10
},
"aggs": {
"brandNameAgg": {
"terms": {
"field": "brandName",
"size": 10
}
},
"brandImgAgg": {
"terms": {
"field": "brandImg",
"size": 10
}
}
}
},
"catelogAgg": {
"terms": {
"field": "catelogId",
"size": 10
},
"aggs": {
"catelogNameAgg": {
"terms": {
"field": "catelogName",
"size": 10
}
}
}
},
"attrs": {
"nested": {
"path": "attrs"
},
"aggs": {
"attrIdAgg": {
"terms": {
"field": "attrs.attrId",
"size": 10
},
"aggs": {
"attrNameAgg": {
"terms": {
"field": "attrs.attrName",
"size": 10
}
}
}
}
}
}
}
}
4.业务代码
=================================SearchController.java==================================
@Controller
public class SearchController {
@Autowired
MallSearchService mallSearchService;
@GetMapping("/list.html")
public String listPage(SearchParam searchParam, Model model){
SearchResult searchResult = mallSearchService.search(searchParam);
model.addAttribute("result",searchResult);
return "list";
}
}
====================================MallSearchServiceImpl.java================================
//去es进行检索
@Override
public SearchResult search(SearchParam searchParam) {
//1.动态构建出要查询的DSL语句
SearchResult searchResult = null;
//1.准备检索请求
SearchRequest searchRequest = buildSearchRequest(searchParam);
try {
//2.执行检索请求
SearchResponse response = client.search(searchRequest, GulimallElasticSearchConfig.COMMON_OPTIONS);
//3.分析响应数据,封装成想要的格式
searchResult = buildSearchResult(response);
} catch (IOException e) {
e.printStackTrace();
}
return searchResult;
}
/** * 1.准备检索请求 * @return * @param searchParam */
private SearchRequest buildSearchRequest(SearchParam searchParam) {
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();//构建DSL语句
/** * 查询:模糊匹配、过滤(按照属性、分类、品牌、价格区间、库存) */
//1.构建bool query
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
//1.1 must -模糊匹配 keyword
if (!StringUtils.isEmpty(searchParam.getKeyword())){
//match
boolQuery.must(QueryBuilders.matchQuery("skuTitle",searchParam.getKeyword()));
}
//1.2 bool-filter catelogId
if (searchParam.getCatalog3Id() != null){
boolQuery.filter(QueryBuilders.termQuery("catelogId",searchParam.getCatalog3Id()));
}
//1.2 bool-filter brandId
if (searchParam.getBrandId() != null && searchParam.getBrandId().size() > 0){
boolQuery.filter(QueryBuilders.termsQuery("brandId",searchParam.getBrandId()));
}
//1.2 bool-filter hasStock
boolQuery.filter(QueryBuilders.termQuery("hasStock",searchParam.getHasStock() == 1));
//1.2 bool-filter skuPrice 1_500/_500/500_
if (!StringUtils.isEmpty(searchParam.getSkuPrice())){
RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery("skuPrice");
String[] s = searchParam.getSkuPrice().split("_");
if (s.length == 2){
//rangeQuery.gte(s[0]).lte(s[1]);
//"_6000".split("_") = {"","6000"}
if (!s[0].isEmpty()){
rangeQuery.gte(s[0]);
}
rangeQuery.lte(s[1]);
}else if (s.length == 1){
if (searchParam.getSkuPrice().startsWith("_")){
rangeQuery.lte(s[0]);
}
if (searchParam.getSkuPrice().endsWith("_")){
rangeQuery.lte(s[0]);
}
}
boolQuery.filter(rangeQuery);
}
//1.2 bool-filter attrs {attrID,attrID,attrID...}
if (searchParam.getAttrs() != null && searchParam.getAttrs().size() > 0){
//attrs=1_5寸:8寸&attrs=2_16G:8G
for (String attr : searchParam.getAttrs()) {
BoolQueryBuilder nestedBoolQuery = QueryBuilders.boolQuery();
//attrs=1_5寸:8寸
String[] s = attr.split("_");//1 5寸:8寸
String attrId = s[0];//1
String[] attrValues = s[1].split(":");//5寸 8寸
nestedBoolQuery.must(QueryBuilders.termQuery("attrs.attrId",attrId));
nestedBoolQuery.must(QueryBuilders.termsQuery("attrs.attrValue",attrValues));
//attrs中的每一个attr 都对应一个 nestedQueryBuilder
NestedQueryBuilder nestedQuery = QueryBuilders.nestedQuery("attrs", nestedBoolQuery, ScoreMode.None);
boolQuery.filter(nestedQuery);
}
}
//封装所有的查询条件
sourceBuilder.query(boolQuery);
/** * 排序、分页、高亮 */
//2.1 排序 sort=hotScore_asc/desc
if (!StringUtils.isEmpty(searchParam.getSort())){
String[] s = searchParam.getSort().split("_");
sourceBuilder.sort(s[0], SortOrder.valueOf(s[1]));
}
//2.2 分页
sourceBuilder.from((searchParam.getPageNum()-1) * EsConstant.PRODUCT_PAGE_SIZE);
sourceBuilder.size(EsConstant.PRODUCT_PAGE_SIZE);
//2.3 高亮 根据关键字 匹配高亮
if (!StringUtils.isEmpty(searchParam.getKeyword())){
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.field("skuTitle");
highlightBuilder.preTags("<b style='color:red'>");
highlightBuilder.postTags("</b>");
sourceBuilder.highlighter(highlightBuilder);
}
/** * 聚合分析 */
//3.1 品牌聚合
TermsAggregationBuilder brand_agg = AggregationBuilders.terms("brand_agg");
brand_agg.field("brandId").size(50);
//品牌聚合的子聚合
brand_agg.subAggregation(AggregationBuilders.terms("brand_name_agg").field("brandName").size(1));
brand_agg.subAggregation(AggregationBuilders.terms("brand_img_agg").field("brandImg").size(1));
sourceBuilder.aggregation(brand_agg);
//3.2 分类聚合
TermsAggregationBuilder catelog_agg = AggregationBuilders.terms("catelog_agg");
catelog_agg.field("catelogId").size(2);
catelog_agg.subAggregation(AggregationBuilders.terms("catelog_name_agg").field("catelogName").size(1));
sourceBuilder.aggregation(catelog_agg);
//3.3 属性聚合
NestedAggregationBuilder attr_agg = AggregationBuilders.nested("attr_agg", "attrs");
//聚合出所有的 attr_id_agg
TermsAggregationBuilder attr_id_agg = AggregationBuilders.terms("attr_id_agg").field("attrs.attrId");
//聚合分析出当前 attr_id对应的名字
attr_id_agg.subAggregation(AggregationBuilders.terms("attr_name_agg").field("attrs.attrName").size(1));
//聚合分析出当前 attr_id对应的所有可能的属性值
attr_id_agg.subAggregation(AggregationBuilders.terms("attr_value_agg").field("attrs.attrValue").size(50));
attr_agg.subAggregation(attr_id_agg);
sourceBuilder.aggregation(attr_agg);
String s = sourceBuilder.toString();
System.out.println(s);
//索引 、 DSL语句
SearchRequest searchRequest = new SearchRequest(new String[]{
EsConstant.PRODUCT_INDEX}, sourceBuilder);
return searchRequest;
}
/** * 3.分析响应数据,封装成想要的格式 * @param response * @return */
private SearchResult buildSearchResult(SearchResponse response,SearchParam searchParam) {
SearchResult searchResult = new SearchResult();
SearchHits hits = response.getHits();
//1.返回所以查询到的商品
List<SkuModel> esModels = new ArrayList<>();
if (hits.getHits() != null && hits.getHits().length > 0){
for (SearchHit hit : hits.getHits()) {
String sourceAsString = hit.getSourceAsString();
SkuModel esModel = JSON.parseObject(sourceAsString,SkuModel.class);
if (!StringUtils.isEmpty(searchParam.getKeyword())) {
HighlightField skuTitle = hit.getHighlightFields().get("skuTitle");
String highLightTitle = skuTitle.getFragments()[0].string();
esModel.setSkuTitle(highLightTitle);
}
esModels.add(esModel);
}
}
searchResult.setProducts(esModels);
//2.当前所有商品涉及到的属性信息
ParsedNested attr_agg = response.getAggregations().get("attr_agg");
List<SearchResult.AttrVo> attrVos = new ArrayList<>();
ParsedLongTerms attr_id_agg = attr_agg.getAggregations().get("attr_id_agg");
for (Terms.Bucket bucket : attr_id_agg.getBuckets()) {
SearchResult.AttrVo attrVo = new SearchResult.AttrVo();
//获取属性的id
Long attrId = bucket.getKeyAsNumber().longValue();
attrVo.setAttrId(attrId);
//获取属性的name
ParsedStringTerms attr_name_agg = bucket.getAggregations().get("attr_name_agg");
String attrName = attr_name_agg.getBuckets().get(0).getKeyAsString();
attrVo.setAttrName(attrName);
//获取属性的value
ParsedStringTerms attr_value_age = bucket.getAggregations().get("attr_value_agg");
List<String> attrValue = attr_value_age.getBuckets().stream().map(item -> {
String keyAsString = item.getKeyAsString();
return keyAsString;
}).collect(Collectors.toList());
attrVo.setAttrValue(attrValue);
attrVos.add(attrVo);
}
searchResult.setAttrs(attrVos);
//3.当前所有商品涉及到的品牌信息
ParsedLongTerms brand_agg = response.getAggregations().get("brand_agg");
List<SearchResult.BrandVo> brandVos = new ArrayList<>();
for (Terms.Bucket bucket : brand_agg.getBuckets()) {
SearchResult.BrandVo brandVo = new SearchResult.BrandVo();
//获取品牌id
String keyAsString = bucket.getKeyAsString();
brandVo.setBrandId(Long.parseLong(keyAsString));
//获取品牌名
ParsedStringTerms brand_name_agg = bucket.getAggregations().get("brand_name_agg");
String brand_name = brand_name_agg.getBuckets().get(0).getKeyAsString();
brandVo.setBrandName(brand_name);
//获取品牌图片
ParsedStringTerms brand_img_agg = bucket.getAggregations().get("brand_img_agg");
String brand_img = brand_img_agg.getBuckets().get(0).getKeyAsString();
brandVo.setBrandImg(brand_img);
brandVos.add(brandVo);
}
searchResult.setBrands(brandVos);
//4.当前所有商品涉及到的分类信息
ParsedLongTerms catelog_agg = response.getAggregations().get("catelog_agg");
List<SearchResult.CatalogVo> catalogVos = new ArrayList<>();
for (Terms.Bucket bucket : catelog_agg.getBuckets()) {
SearchResult.CatalogVo catalogVo = new SearchResult.CatalogVo();
//得到分类id
String keyAsString = bucket.getKeyAsString();
catalogVo.setCatalogId(Long.parseLong(keyAsString));
//得到分类名
ParsedStringTerms catelog_name_agg = bucket.getAggregations().get("catelog_name_agg");
String catelog_name = catelog_name_agg.getBuckets().get(0).getKeyAsString();
catalogVo.setCatalogName(catelog_name);
catalogVos.add(catalogVo);
}
searchResult.setCatalogs(catalogVos);
//5.分页信息-页码
searchResult.setPageNum(searchParam.getPageNum());
//5.分页信息-总记录数
long total = hits.getTotalHits().value;
searchResult.setTotal(total);
//5.分页信息-总页码
int totoalPages = (int) total%EsConstant.PRODUCT_PAGE_SIZE == 0 ? (int) total/EsConstant.PRODUCT_PAGE_SIZE : (int) (total/EsConstant.PRODUCT_PAGE_SIZE + 1);
searchResult.setTotalPage(totoalPages);
return null;
}
七、CompletableFuture-异步编排
1.线程池回顾
参考博客:《Java并发编程的艺术》2 第九章 Java中的线程池_HotRabbit.的博客-CSDN博客
2.异步
- Future 是 Java 5 添加的类,用来描述一个异步计算的结果。你可以使用
isDone
方法检查计 算是否完成,或者使用get
阻塞住调用线程,直到计算完成返回结果,你也可以使用cancel
方法停止任务的执行。 - 虽然
Future
以及相关使用方法提供了异步执行任务的能力,但是对于结果的获取却是很不 方便,只能通过阻塞或者轮询的方式得到任务的结果。阻塞的方式显然和我们的异步编程的 初衷相违背,轮询的方式又会耗费无谓的 CPU 资源,而且也不能及时地得到计算结果,为 什么不能用观察者设计模式当计算结果完成及时通知监听者呢? - 很多语言,比如 Node.js,采用回调的方式实现异步编程。Java 的一些框架,比如 Netty,自 己扩展了 Java 的
Future
接口,提供了addListener
等多个扩展方法;Google guava 也提供了 通用的扩展 Future;Scala 也提供了简单易用且功能强大的 Future/Promise 异步编程模式。 - 在 Java 8 中, 新增加了一个包含 50 个方法左右的类: CompletableFuture,提供了非常强大的 Future 的扩展功能,可以帮助我们简化异步编程的复杂性,提供了函数式编程的能力,可以 通过回调的方式处理计算结果,并且提供了转换和组合 CompletableFuture 的方法。 CompletableFuture 类实现了 Future 接口,所以你还是可以像以前一样通过
get
方法阻塞或 者轮询的方式获得结果,但是这种方式不推荐使用。 - CompletableFuture 和 FutureTask 同属于 Future 接口的实现类,都可以获取线程的执行结果。
3.创建异步对象
CompletableFuture 提供了四个静态方法来创建一个异步操作。
get方法会阻塞当前线程,直到提交的任务执行完
3.1 计算完成时回调方法
whenComplete 可以处理正常和异常的计算结果,exceptionally 处理异常情况。
whenComplete 和 whenCompleteAsync 的区别:
- whenComplete:是执行当前任务的线程执行继续执行 whenComplete 的任务。
- whenCompleteAsync:是执行把 whenCompleteAsync 这个任务继续提交给线程池 来进行执行
方法不以 Async 结尾,意味着 Action 使用相同的线程执行,而 Async 可能会使用其他线程 执行(如果是使用相同的线程池,也可能会被同一个线程选中执行)
3.2 handle方法
和 complete 一样,可对结果做最后的处理(可处理异常),可改变返回值。
3.3 线程串行化方法
- thenApply 方法:当一个线程依赖另一个线程时,获取上一个任务返回的结果,并返回当前 任务的返回值。
- thenAccept 方法:消费处理结果。接收任务的处理结果,并消费处理,无返回结果。
- thenRun 方法:只要上面的任务执行完成,就开始执行 thenRun,只是处理完任务后,执行 thenRun 的后续操作
带有 Async 默认是异步执行的。同之前。
以上都要前置任务成功完成。 Function<? super T , ? extends U>
- T:上一个任务返回结果的类型
- U:当前任务的返回值类型
3.4 两任务组合-都要完成
两个任务必须都完成,触发该任务。
- thenCombine:组合前两个 future,获取前两个 future 的返回结果,并返回当前任务的返回值
- thenAcceptBoth:组合前两个 future,获取前两个 future 任务的返回结果,然后处理任务,没有 返回值。
- runAfterBoth:组合前两个 future,不需要获取 future 的结果,只需前两个 future 处理完任务后, 处理该任务。
3.5 两任务组合-一个完成
当两个任务中,任意一个 future 任务完成的时候,执行任务。
- applyToEither:两个任务有一个执行完成,获取它的返回值,处理任务并有新的返回值。
- acceptEither:两个任务有一个执行完成,获取它的返回值,处理任务,没有新的返回值。
- runAfterEither:两个任务有一个执行完成,不需要获取 future 的结果,处理任务,也没有返 回值
3.6 多任务组合
- allOf:等待所有任务完成
- anyOf:只要有一个任务完成
八、商品详情
配置详情页路由
1. 封装vo
封装一个详情页的skuvo
@ToString
@Data
public class SkuItemVo {
//1、sku基本信息的获取 pms_sku_info
private SkuInfoEntity info;
private boolean hasStock = true;
//2、sku的图片信息 pms_sku_images
private List<SkuImagesEntity> images;
//3、获取spu的销售属性组合
private List<SkuItemSaleAttrVo> saleAttr;
//4、获取spu的介绍
private SpuInfoDescEntity desc;
//5、获取spu的规格参数信息
private List<SpuItemAttrGroupVo> groupAttrs;
//6、秒杀商品的优惠信息
//private SeckillSkuVo seckillSkuVo;
}
@Data
@ToString
public class SkuItemSaleAttrVo {
private Long attrId;
private String attrName;
private List<AttrValueWithSkuIdVo> attrValues;
//private String attrValue 属性值
//private String skuIds 该属性值对应的skuId的集合
}
@Data
@ToString
public class SpuItemAttrGroupVo {
private String groupName;
//attrId,attrName,attrValue
private List<Attr> attrs;
}
2.使用异步编排提高效率
@Override
public SkuItemVo item(Long skuId) {
SkuItemVo skuItemVo = new SkuItemVo();
CompletableFuture<SkuInfoEntity> infoFuture = CompletableFuture.supplyAsync(() -> {
//1、sku基本信息的获取 pms_sku_info
SkuInfoEntity skuInfoEntity = this.getById(skuId);
skuItemVo.setInfo(skuInfoEntity);
return skuInfoEntity;
}, executor);
//2、sku的图片信息 pms_sku_images
CompletableFuture<Void> imageFuture = CompletableFuture.runAsync(() -> {
List<SkuImagesEntity> skuImagesEntities = skuImagesService.list(new QueryWrapper<SkuImagesEntity>().eq("sku_id", skuId));
skuItemVo.setImages(skuImagesEntities);
}, executor);
//3、获取spu的销售属性组合-> 依赖1 获取spuId
CompletableFuture<Void> saleFuture = infoFuture.thenAcceptAsync((info) -> {
List<SkuItemSaleAttrVo> saleAttrVos = skuSaleAttrValueService.listSaleAttrs(info.getSpuId());
skuItemVo.setSaleAttr(saleAttrVos);
}, executor);
//4、获取spu的介绍-> 依赖1 获取spuId
CompletableFuture<Void> descFuture = infoFuture.thenAcceptAsync((info) -> {
SpuInfoDescEntity byId = spuInfoDescService.getById(info.getSpuId());
skuItemVo.setDesc(byId);
}, executor);
//5、获取spu的规格参数信息-> 依赖1 获取spuId catalogId
CompletableFuture<Void> attrFuture = infoFuture.thenAcceptAsync((info) -> {
List<SpuItemAttrGroupVo> spuItemAttrGroupVos=productAttrValueService.getProductGroupAttrsBySpuId(info.getSpuId(), info.getCatalogId());
skuItemVo.setGroupAttrs(spuItemAttrGroupVos);
}, executor);
// //6、秒杀商品的优惠信息
// CompletableFuture<Void> seckFuture = CompletableFuture.runAsync(() -> {
// R r = seckillFeignService.getSeckillSkuInfo(skuId);
// if (r.getCode() == 0) {
// SeckillSkuVo seckillSkuVo = r.getData(new TypeReference<SeckillSkuVo>() {
// });
// long current = System.currentTimeMillis();
// //如果返回结果不为空且活动未过期,设置秒杀信息
// if (seckillSkuVo != null&¤t<seckillSkuVo.getEndTime()) {
// skuItemVo.setSeckillSkuVo(seckillSkuVo);
// }
// }
// }, executor);
//等待所有任务执行完成
try {
CompletableFuture.allOf(imageFuture, saleFuture, descFuture, attrFuture).get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
return skuItemVo;
}
/** * 商品详情页 * * @param skuId * @return */
/* @Override public SkuItemVo item(Long skuId) { SkuItemVo skuItemVo = new SkuItemVo(); //1、sku基本信息的获取 pms_sku_info SkuInfoEntity skuInfoEntity = this.getById(skuId); skuItemVo.setInfo(skuInfoEntity); Long spuId = skuInfoEntity.getSpuId(); Long catalogId = skuInfoEntity.getCatalogId(); //2、sku的图片信息 pms_sku_images List<SkuImagesEntity> skuImagesEntities = skuImagesService.list(new QueryWrapper<SkuImagesEntity>().eq("sku_id", skuId)); skuItemVo.setImages(skuImagesEntities); //3、获取spu的销售属性组合-> 依赖1 获取spuId List<SkuItemSaleAttrVo> saleAttrVos = skuSaleAttrValueService.listSaleAttrs(spuId); skuItemVo.setSaleAttr(saleAttrVos); //4、获取spu的介绍-> 依赖1 获取spuId SpuInfoDescEntity byId = spuInfoDescService.getById(spuId); skuItemVo.setDesc(byId); //5、获取spu的规格参数信息-> 依赖1 获取spuId catalogId List<SpuItemAttrGroupVo> spuItemAttrGroupVos = productAttrValueService.getProductGroupAttrsBySpuId(spuId, catalogId); skuItemVo.setGroupAttrs(spuItemAttrGroupVos); //TODO 6、秒杀商品的优惠信息 return skuItemVo; } */
边栏推荐
猜你喜欢
TQP3M9009电路设计
TC358860XBG BGA65 东芝桥接芯片 HDMI转MIPI
TeamCode 产品 UI 全新升级,快来体验吧
Case | industrial iot solutions, steel mills high-performance security for wisdom
云服务器web项目部署详解
D类音频功放NS4110B电路设计
【plang1.4.3】语言新特性:集合
将ORCAD原理图导入allegro中进行PCB设计
The use and simulation of vector implementation:
GM7150 CVBS转BT656视频解码芯片详细内容及设计要求
随机推荐
【MQ-3 Alcohol Detector and Arduino Detect Alcohol】
[Arduino connects the clock module to display the time on LCD1602]
Comparison between Boda Industrial Cloud and Alibaba Cloud
【科普贴】I2C接口详解——偏硬件解析
GM8775C MIPI转LVDS调试心得分享
【Arduino connects DHT11 humidity and temperature sensor】
GM8284DD,GM8285C,GM8913,GM8914,GM8905C,GM8906C,国腾振芯LVDS类芯片
振芯科技GM8285C:功能TTL转LVDS芯片简介
机械臂运动学解析
笔记本电脑充电问题
LT8918L LVDS转MIPI芯片技术支持资料
408-二叉树-先序中序后序层次遍历
【科普贴】SPI接口详解
Comparative analysis of mobile cloud IoT pre-research and Alibaba Cloud development
向龙芯2K1000板子上烧写中标麒麟系统
HDMI转MIPI CSI东芝转换芯片-TC358743XBG/TC358749XBG
LL(1)文法 :解决 if-else/if-else 产生式二义性问题
【科普贴】SD卡接口协议详解
读取FBX文件踩坑清单
电子密码锁_毕设‘指导’