目录

  • 一、详情数据
  • 二、查询详情
  • 三、sku 组合切换
  • 四、关键 SQL

一、详情数据


封装成 vo 如下:

SkuItemVo:

@Data
public class SkuItemVo {//1、sku基本信息获取  pms_sku_infoSkuInfoEntity info;boolean hasStock = true;//2、sku的图片信息  pms_sku_imagesList<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 {@Beanpublic 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 {@Resourceprivate 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_infoSkuInfoEntity 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_descSpuInfoDescEntity 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_imagesCompletableFuture<Void> imageFuture = CompletableFuture.runAsync(() -> {List<SkuImagesEntity> images = imagesService.getImagesBySkuId(skuId);skuItemVo.setImages(images);}, executor);//等到所有任务都完成CompletableFuture.allOf(saleAttrFuture,descFuture,baseAttrFuture,imageFuture).get();return skuItemVo;
}

getSaleAttrsBySpuId 方法的实现:

@Overridepublic 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">SELECTproduct.spu_id,pag.attr_group_id,pag.attr_group_name,product.attr_id,product.attr_name,product.attr_valueFROMpms_product_attr_value productLEFT JOIN pms_attr_attrgroup_relation paar ON product.attr_id = paar.attr_idLEFT JOIN pms_attr_group pag ON paar.attr_group_id = pag.attr_group_idWHEREproduct.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、取出他们的交集,得到 skuIdvar 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

SELECTssav.`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`

谷粒商城 高级篇 (十四) ---------- 商品详情相关推荐

  1. 谷粒商城 高级篇 (十六) --------- 社交登录

    目录 前言 一.OAuth 2.0 二.微博登陆准备工作 三.整合微博登录 1.引导用户到如下地址 2. 授权登录后进入回调函数 3. Session共享问题解决 ① session复制 ② 客户端存 ...

  2. 谷粒商城高级篇上(未完待续)

    谷粒商城高级篇(上)保姆级整理 之前整理了基础篇,Typora提示将近20000词,谷粒商城基础篇保姆级整理 在学高级篇的时候,不知不觉又整理了两万多词,做了一阶段,先发出来,剩余部分整理好了再发.自 ...

  3. 谷粒商城高级篇(38)——异步编排之商品详情查询

    异步编排之商品详情查询 异步编排 CompletableFuture介绍 创建异步对象 计算完成时回调方法 handle 方法 线程串行化方法 两任务组合 全部完成 一个完成即可 多任务组合 业务描述 ...

  4. 【谷粒商城高级篇】商品服务 商品上架

    谷粒商城笔记合集 分布式基础篇 分布式高级篇 高可用集群篇 ===简介&环境搭建=== ===Elasticsearch=== 项目简介与分布式概念(第一.二章) Elasticsearch: ...

  5. 【谷粒商城高级篇】商城业务:商品检索

    谷粒商城笔记合集 分布式基础篇 分布式高级篇 高可用集群篇 ===简介&环境搭建=== ===Elasticsearch=== 项目简介与分布式概念(第一.二章) Elasticsearch: ...

  6. 【谷粒商城高级篇】Elasticsearch:全文检索

    谷粒商城笔记合集 分布式基础篇 分布式高级篇 高可用集群篇 ===简介&环境搭建=== ===Elasticsearch=== 项目简介与分布式概念(第一.二章) Elasticsearch: ...

  7. 谷粒商城高级篇笔记1

    这里写自定义目录标题 0.ElasticSearch 1.Nginx配置域名问题 01.Nginx(反向代理) 配置 02.Nginx(负载均衡)+ 网关 配置 03.Nginx动静分离 2.JMet ...

  8. 谷粒商城-高级篇-aiueo

    105 初步检索 105.1 _cat GET /_cat/nodes : 查看所有节点 GET /_cat/health : 查看es健康状况 GET /_cat/master : 查看主节点 GE ...

  9. 谷粒商城高级篇爬坑笔记--错误异常信息乱码问题

    由于高级篇开发相对较多,配置的内容较少,本人编写过程中没有遇到特别大的问题,唯一的问题就是消息乱码: 项目定义了如下的异常类: UNKNOW_EXCEPTION(10000,"系统未知异常& ...

最新文章

  1. 使用SIFT特征提取和K-Means方法对图片进行分类
  2. 怎么用python处理数据_Python数据清洗 - 洗什么?怎么洗?看完就明白了
  3. IT技术人,“三十而已”
  4. Python 之 Python2 和 Python3 的区别
  5. C语言中的strncmp
  6. 我和阿里巴巴的孽缘(一)
  7. ABBYY FineReader 12PDF选项卡之图像及文字设置
  8. Eclipse“ctrl+左键”链到实现类
  9. 链表根据主元切分成3段
  10. quotes 整站数据爬取存mongo
  11. Java 使用 OpenCV (二)之 视频编解码器
  12. 三层链路冗余-单宿主网络(拓扑图及思路)
  13. H5热门游戏模板案例解读:贪吃蛇玩法的新高度
  14. 如何卸载快压病毒流氓软件--不停自动下载安装App
  15. 给电脑C盘系统盘瘦身的四种方法
  16. Communications link failure错误(亲测有效)
  17. python入门容器-列表ListDay05
  18. 被迫改变生活方式对少数族群的微生物群和健康的影响
  19. Eclipse中mvn install 报错error in opening zip file
  20. jtable 表头 透明_日本艺术家携手岡本打造了一对“拥薄透明人”!为情侣们定制了一份专属浪漫!这个七夕,一起拥抱爱吧!...

热门文章

  1. 小米有品开出全球首家商业旗舰店:加速新零售扩张
  2. 如何用Python抓网页,案例教程都总结到位了
  3. 统计学学习日记:L10-假设检验p值
  4. 19号笔刷 ps_【精品】PS绘画19号笔刷正确使用方法
  5. 对应于正态分布的拉丁超立方抽样——Python版
  6. 抽象基类与接口,共性与个性的选择!(区别)
  7. 小米路由开启SSH访问权限
  8. JavaScript之减速运动的实现
  9. BI选型之国内外BI产品对比分析
  10. 块元素盒子内容被撑开