子丹商城——Sku商品详情页

一、配置对item.zidanmall.com的域名支持

1、首先配置DNS解析;

2、配置nginx的代理规则(这一条我们其实之前已经配置过了):

40.jpg

动静分离的路径 /static/ 配置也已经完成;

3、配置gateway网关路由规则:

- id: zidanmall_host_route
  uri: lb://zidanmall-product
  predicates:
    - Host=zidanmall.com, item.zidanmall.com

二、完成后端核心代码

1、核心返回实体类 SkuItemVo.java:

@Data
public class SkuItemVo {

    //1.sku基本信息 pms_sku_info
    SkuInfoEntity info;

    //是否有货
    Boolean hasStock=true;

    //2.sku 图片  pms_sku_images
    List<SkuImagesEntity> images;

    //3.spu 销售属性(sku所有组合)
    List<SkuItemSaleAttrVo> saleAttr;

    //4.spu介绍
    SpuInfoDescEntity desp;

    //5.spu规格参数
    List<SpuItemAttrGroupVo> groupAttrs;
}

2、Controller类ItemController.java:

@Controller
public class ItemController {
    @Autowired
    SkuInfoService skuInfoService;

    /**
     * 展示当前skuId对应的商品详情
     * @param skuId
     * @return
     */
    @GetMapping("/{skuId}.html")
    public String skuItem(@PathVariable("skuId") Long skuId, Model model){
        SkuItemVo item = skuInfoService.item(skuId);
        System.out.println(item);
        model.addAttribute("item", item);
        return "item";
    }
}

3、业务类SkuInfoServiceImpl.java中的item()方法:

——注意这个方法后面会被做 ComplatableFuture 异步编排优化

/**
 * 查询skuId对应的页面需要的详情
 * 1、sku基本信息获取 pms_sku_info
 * 2、sku图片信息 pms_sku_images
 * 3、获取spu的所有销售属性的组合
 * 4、获取spu的介绍
 * 5、获取spu的规格参数信息
 * @param skuId
 * @return
 */
@Override
public SkuItemVo item(Long skuId) {
    SkuItemVo skuItemVo=new SkuItemVo();

    //1.sku基本信息 pms_sku_info
    SkuInfoEntity info = getById(skuId);
    skuItemVo.setInfo(info);

    //2、sku图片信息 pms_sku_images
    List<SkuImagesEntity> images = imagesService.getImagesBySkuId(skuId);
    skuItemVo.setImages(images);

    //3.spu 销售属性(sku所有组合)
    List<SkuItemSaleAttrVo> saleAttrVos = skuSaleAttrValueService.getSaleAttrsBySpuId(info.getSpuId());
    skuItemVo.setSaleAttr(saleAttrVos);

    //4.spu介绍
    SpuInfoDescEntity spuInfoDescEntity = spuInfoDescService.getById(info.getSpuId());
    skuItemVo.setDesp(spuInfoDescEntity);

    //5.spu规格参数
    List<SpuItemAttrGroupVo> groupVos = attrGroupService.getAttrGroupWithAttrsBySpuId(info.getSpuId(), info.getCatalogId());
    skuItemVo.setGroupAttrs(groupVos);

    return skuItemVo;
}

三、前端渲染

前端渲染的其它地方都比较简单,比较复杂的是:多个销售属性自由组合,点击切换到不同的配对结果对应的skuId详情页的功能

1、html部分:

<div class="box-attr clear" th:each="attr:${item.saleAttr}">  <!--每个属性名遍历,选择‘颜色’、‘内存’等-->
   <dl>
      <dt>选择[[${attr.attrName}]]</dt>
      <dd th:each="val:${attr.attrValues}">
         <a href="#" th:attr="skus=${val.skuIds},
            class=${#lists.contains(#strings.listSplit(val.skuIds, ','), item.info.skuId.toString())}?'sku_attr_value checked':'sku_attr_value'">
            [[${val.attrValue}]]
         </a>
      </dd>
   </dl>
</div>

2、javascript部分:

<script type="text/javascript">
   $(".sku_attr_value").click(function () {
      //1.点击的元素添加自定义属性。识别当前点击的
      var skus = new Array();
      $(this).addClass('clicked');
      var cur = $(this).attr("skus").split(",");
      //当前被点击的所有skuId组合
      skus.push(cur);
      //移除同一行的所有属性值的checked的class
      $(this).parent().parent().find(".sku_attr_value").removeClass("checked");

      //找出当前的所有的被checked的属性值对应的skuId数组,放入skus中
      $("a[class='sku_attr_value checked']").each(function () {
         skus.push($(this).attr("skus").split(","));
      })

      //2.取出交集 得到skuId
      var filterElm = skus[0];  //第一个0号位的肯定是刚刚被click的那个,因为实第一个被放入skus中的
      for (var i = 1; i < skus.length; i++) {
         filterElm = $(filterElm).filter(skus[i]);
      }

      //3.跳转
      location.href = "http://item.zidanmall.com/" + filterElm[0] + ".html";
   })

   //修改当前被“checked”的属性的颜色
   $(function () {
      $(".sku_attr_value").parent().css({"border": "solid 1px #CCC"})
      $("a[class='sku_attr_value checked']").parent().css({"border": "solid 1px red"})
   })
</script>

到这里,整个前端sku商品详情页就做完了;

3、效果预览:

42.jpg

切换一组销售属性值看看效果:

43.jpg

Sku属性组合切换功能正常可用!


四、service层逻辑ComplatableFuture异步编排优化

1、我们先自定义一个线程池:

ThreadPoolConfigProperties.java:
@ConfigurationProperties(prefix = "zidanmall.thread")
@Component
@Data
public class ThreadPoolConfigProperties {
    private Integer coreSize;
    private Integer maxSize;
    private Integer keepAliveTime;
}
MyThreadConfig.java:
@Configuration
public class MyThreadConfig {
    @Bean
    public ThreadPoolExecutor threadPoolExecutor(ThreadPoolConfigProperties properties){
        System.out.println(properties);
        return new ThreadPoolExecutor(properties.getCoreSize(),
                properties.getMaxSize(),
                properties.getKeepAliveTime(),
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(100000),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());
    }
}

application.yml:

zidanmall:
  thread:
    core-size: 20
    max-size: 200
    keep-alive-time: 10

测试可用;

2、开始使用ComplatableFuture进行异步编排,提升性能:

/**
 * 查询skuId对应的页面需要的详情
 * 1、sku基本信息获取 pms_sku_info
 * 2、sku图片信息 pms_sku_images
 * 3、获取spu的所有销售属性的组合
 * 4、获取spu的介绍
 * 5、获取spu的规格参数信息
 * @param skuId
 * @return
 */
@Override
public SkuItemVo item(Long skuId) throws ExecutionException, InterruptedException {
    SkuItemVo skuItemVo=new SkuItemVo();

    CompletableFuture<SkuInfoEntity> infoFuture = CompletableFuture.supplyAsync(() -> {
        //1.sku基本信息 pms_sku_info
        SkuInfoEntity info = getById(skuId);
        skuItemVo.setInfo(info);
        return info;
    }, executor);

    CompletableFuture<Void> saleAttrFuture = infoFuture.thenAcceptAsync(res -> {
        //3.spu 销售属性(sku所有组合)
        List<SkuItemSaleAttrVo> saleAttrVos = skuSaleAttrValueService.getSaleAttrsBySpuId(res.getSpuId());
        skuItemVo.setSaleAttr(saleAttrVos);
    }, executor);

    CompletableFuture<Void> descFuture = infoFuture.thenAcceptAsync(res -> {
        //4.spu介绍
        SpuInfoDescEntity spuInfoDescEntity = spuInfoDescService.getById(res.getSpuId());
        skuItemVo.setDesp(spuInfoDescEntity);
    }, executor);

    CompletableFuture<Void> baseAttrFuture = infoFuture.thenAcceptAsync(res -> {
        //5.spu规格参数
        List<SpuItemAttrGroupVo> groupVos = attrGroupService.getAttrGroupWithAttrsBySpuId(res.getSpuId(), res.getCatalogId());
        skuItemVo.setGroupAttrs(groupVos);
    }, executor);

    CompletableFuture<Void> imgFuture = CompletableFuture.runAsync(() -> {
        //2、sku图片信息 pms_sku_images
        List<SkuImagesEntity> images = imagesService.getImagesBySkuId(skuId);
        skuItemVo.setImages(images);
    }, executor);

    //等待所有任务都完成
    CompletableFuture.allOf(saleAttrFuture, descFuture, baseAttrFuture, imgFuture).get();

    return skuItemVo;
}

到这里,商品详情页的功能就全部完成了;

44.jpg

jiguiquan@163.com

文章作者信息...

留下你的评论

*评论支持代码高亮<pre class="prettyprint linenums">代码</pre>

相关推荐