谷粒商城10——搜索、商品详情、异步编排

六、商城业务-搜索页面

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 接口的实现类,都可以获取线程的执行结果。

image-20220726170142885

3.创建异步对象

CompletableFuture 提供了四个静态方法来创建一个异步操作。

image-20220726172201396

image-20220726172748997

get方法会阻塞当前线程,直到提交的任务执行完

image-20220726173028477

3.1 计算完成时回调方法

image-20220726203449896

whenComplete 可以处理正常和异常的计算结果,exceptionally 处理异常情况。

whenComplete 和 whenCompleteAsync 的区别:

  • whenComplete:是执行当前任务的线程执行继续执行 whenComplete 的任务。
  • whenCompleteAsync:是执行把 whenCompleteAsync 这个任务继续提交给线程池 来进行执行

方法不以 Async 结尾,意味着 Action 使用相同的线程执行,而 Async 可能会使用其他线程 执行(如果是使用相同的线程池,也可能会被同一个线程选中执行)

image-20220726204338389

3.2 handle方法

和 complete 一样,可对结果做最后的处理(可处理异常),可改变返回值。

image-20220726204912755

3.3 线程串行化方法

image-20220726205819559

  • 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:只要有一个任务完成

八、商品详情

配置详情页路由

image-20220728145905077

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&&current<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;
    }
    */

image-20220729133444938

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HotRabbit.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值