谷粒商城 高级篇 (十四) ---------- 商品详情 雨点打透心脏的1/2处 2024-04-06 09:28 40阅读 0赞 #### 目录 #### * 一、详情数据 * 二、查询详情 * 三、sku 组合切换 * 四、关键 SQL -------------------- ## 一、详情数据 ## ![在这里插入图片描述][622dacaf5f1e44b89250472ef3c7daa2.png] 封装成 vo 如下: **SkuItemVo:** @Data public class SkuItemVo { //1、sku基本信息获取 pms_sku_info SkuInfoEntity info; boolean hasStock = true; //2、sku的图片信息 pms_sku_images List<SkuImagesEntity> images; //3、获取spu的销售属性组合。 List<SkuItemSaleAttrVo> saleAttr; //4、获取spu的介绍 SpuInfoDescEntity desp; //5、获取spu的规格参数信息。 List<SpuItemAttrGroupVo> groupAttrs; SeckillInfoVo seckillInfo;//当前商品的秒杀优惠信息 } **SkuItemSaleAttrVo:** package com.fancy.gulimall.product.vo; import lombok.Data; import lombok.ToString; import java.util.List; @ToString @Data public class SkuItemSaleAttrVo { private Long attrId; private String attrName; private List<AttrValueWithSkuIdVo> attrValues; } **SpuItemAttrGroupVo:** package com.fancy.gulimall.product.vo; import lombok.Data; import lombok.ToString; import java.util.List; @Data @ToString public class SpuItemAttrGroupVo { private String groupName; private List<Attr> attrs; } ## 二、查询详情 ## 优化方面采用异步编排,要使用异步的话,首先我们需要自定义线程池。。。 package com.fancy.gulimall.product.config; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.concurrent.Executors; import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; @EnableConfigurationProperties(ThreadPoolConfigProperties.class) @Configuration public class MyThreadConfig { @Bean public ThreadPoolExecutor threadPoolExecutor(ThreadPoolConfigProperties pool) { return new ThreadPoolExecutor( pool.getCoreSize(), pool.getMaxSize(), pool.getKeepAliveTime(), TimeUnit.SECONDS, new LinkedBlockingDeque<>(100000), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy() ); } } 要想实现从 application.properties 中获取数据,我们需要创建一个配置文件 package com.fancy.gulimall.product.config; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; @ConfigurationProperties(prefix = "gulimall.thread") // @Component @Data public class ThreadPoolConfigProperties { private Integer coreSize; private Integer maxSize; private Integer keepAliveTime; } 提示要导入依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> 相应的值在 application.properties 中配置与取出 #配置线程池 gulimall.thread.coreSize=20 gulimall.thread.maxSize=200 gulimall.thread.keepAliveTime=10 商品详情的请求: package com.fancy.gulimall.product.web; import com.fancy.gulimall.product.service.SkuInfoService; import com.fancy.gulimall.product.vo.SkuItemVo; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import javax.annotation.Resource; import java.util.concurrent.ExecutionException; @Controller public class ItemController { @Resource private SkuInfoService skuInfoService; /** * 展示当前sku的详情 * @param skuId * @return */ @GetMapping("/{skuId}.html") public String skuItem(@PathVariable("skuId") Long skuId, Model model) throws ExecutionException, InterruptedException { System.out.println("准备查询" + skuId + "详情"); SkuItemVo vos = skuInfoService.item(skuId); model.addAttribute("item",vos); return "item"; } } 相应的处理方法:采用异步编排 @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 的销售属性组合。 List<SkuItemSaleAttrVo> saleAttrVos = skuSaleAttrValueService.getSaleAttrsBySpuId(res.getSpuId()); skuItemVo.setSaleAttr(saleAttrVos); }, executor); CompletableFuture<Void> descFuture = infoFuture.thenAcceptAsync(res -> { //4、获取 spu 的介绍 pms_spu_info_desc SpuInfoDescEntity spuInfoDescEntity = spuInfoDescService.getById(res.getSpuId()); skuItemVo.setDesp(spuInfoDescEntity); }, executor); CompletableFuture<Void> baseAttrFuture = infoFuture.thenAcceptAsync(res -> { //5、获取 spu 的规格参数信息。 List<SpuItemAttrGroupVo> attrGroupVos = attrGroupService.getAttrGroupWithAttrsBySpuId(res.getSpuId(), res.getCatalogId()); skuItemVo.setGroupAttrs(attrGroupVos); }, executor); //2、sku 的图片信息 pms_sku_images CompletableFuture<Void> imageFuture = CompletableFuture.runAsync(() -> { List<SkuImagesEntity> images = imagesService.getImagesBySkuId(skuId); skuItemVo.setImages(images); }, executor); //等到所有任务都完成 CompletableFuture.allOf(saleAttrFuture,descFuture,baseAttrFuture,imageFuture).get(); return skuItemVo; } getSaleAttrsBySpuId 方法的实现: @Override public List<SkuItemSaleAttrVo> getSaleAttrBySpuId(Long spuId) { SkuSaleAttrValueDao baseMapper = this.getBaseMapper(); List<SkuItemSaleAttrVo> saleAttrVos = baseMapper.getSaleAttrBySpuId(spuId); return saleAttrVos; } baseMapper.getSaleAttrBySpuId 对应的 mapper 映射文件中方法如下: <resultMap id="spuAttrGroup" type="com.fancy.gulimall.product.vo.SpuItemAttrGroupVo"> <result property="groupName" column="attr_group_name"/> <collection property="attrs" ofType="com.xunqi.gulimall.product.vo.Attr"> <result property="attrId" column="attr_id"></result> <result property="attrName" column="attr_name"></result> <result property="attrValue" column="attr_value"></result> </collection> </resultMap> <select id="getAttrGroupWithAttrsBySpuId" resultMap="spuAttrGroup"> SELECT product.spu_id, pag.attr_group_id, pag.attr_group_name, product.attr_id, product.attr_name, product.attr_value FROM pms_product_attr_value product LEFT JOIN pms_attr_attrgroup_relation paar ON product.attr_id = paar.attr_id LEFT JOIN pms_attr_group pag ON paar.attr_group_id = pag.attr_group_id WHERE product.spu_id = #{spuId} AND pag.catelog_id = #{catalogId} </select> getAttrGroupWithAttrsBySpuId 方法的实现: @Override public List<SpuItemAttrGroupVo> getAttrGroupWithAttrsBySpuId(Long spuId, Long catalogId) { //1、查出当前spu对应的所有属性的分组信息以及当前分组下的所有属性对应的值 AttrGroupDao baseMapper = this.getBaseMapper(); List<SpuItemAttrGroupVo> vos = baseMapper.getAttrGroupWithAttrsBySpuId(spuId,catalogId); return vos; } getImagesBySkuId 方法的实现: @Override public List<SkuImagesEntity> getImagesBySkuId(Long skuId) { List<SkuImagesEntity> imagesEntities = this.baseMapper.selectList(new QueryWrapper<SkuImagesEntity>().eq("sku_id", skuId)); return imagesEntities; } ## 三、sku 组合切换 ## 页面遍历 <div class="box-attr clear" th:each="attr:${item.saleAttr}"> <dl> <dt>选择[[${attr.attrName}]]</dt> <dd th:each="vals:${attr.attrValues}"> <a class="sku_attr_value" th:attr="skus=${vals.skuIds},class=${#lists.contains(#strings.listSplit(vals.skuIds,','), item.info.skuId.toString())?'sku_attr_value checked':'sku_attr_value'}" > [[${vals.attrValue}]] <!-- <img src="/static/item/img/59ddfcb1Nc3edb8f1.jpg" /> --> </a> </dd> </dl> </div> 动态切换 $(".sku_attr_value").click(function(){ //1、点击的元素先添加上自定义的属性。为了识别我们是刚才被点击的var skus = new Array(); $(this).addClass("clicked"); var curr = $(this).attr("skus").split(","); //当前被点击的所有 sku 组合数组放进去 skus.push(curr); //去掉同一行的所有的 checked $(this).parent().parent().find(".sku_attr_value").removeClass("checked"); $("a[class='sku_attr_value checked']").each(function(){ skus.push($(this).attr("skus").split(",")); }); console.log(skus); //2、取出他们的交集,得到 skuId var filterEle = skus[0]; for(var i = 1;i<skus.length;i++){ filterEle = $(filterEle).filter(skus[i]); } console.log(filterEle[0]); location.href = "http://item.gulimall.com/"+filterEle[0]+".html"; //4、跳转 }); ## 四、关键 SQL ## SELECT ssav.`attr_id` attr_id, ssav.`attr_name` attr_name, ssav.`attr_value`, GROUP_CONCAT(DISTINCT info.`sku_id`) sku_ids FROM `pms_sku_info` info LEFT JOIN `pms_sku_sale_attr_value` ssav ON ssav.`sku_id`=info.`sku_id` WHERE info.`spu_id`=#{spuId} GROUP BY ssav.`attr_id`,ssav.`attr_name`,ssav.`attr_value` ![在这里插入图片描述][4848b0e32a7644acb936e4bb7a5e01ce.png] [622dacaf5f1e44b89250472ef3c7daa2.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/06/0bfc384cb1ad48f2b4c4fb501f85a20a.png [4848b0e32a7644acb936e4bb7a5e01ce.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/06/56e67596124c40f2b5243100a0fb8c59.png
还没有评论,来说两句吧...