谷粒商城 高级篇 (十四) ---------- 商品详情
目录
- 一、详情数据
- 二、查询详情
- 三、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`
谷粒商城 高级篇 (十四) ---------- 商品详情相关推荐
- 谷粒商城 高级篇 (十六) --------- 社交登录
目录 前言 一.OAuth 2.0 二.微博登陆准备工作 三.整合微博登录 1.引导用户到如下地址 2. 授权登录后进入回调函数 3. Session共享问题解决 ① session复制 ② 客户端存 ...
- 谷粒商城高级篇上(未完待续)
谷粒商城高级篇(上)保姆级整理 之前整理了基础篇,Typora提示将近20000词,谷粒商城基础篇保姆级整理 在学高级篇的时候,不知不觉又整理了两万多词,做了一阶段,先发出来,剩余部分整理好了再发.自 ...
- 谷粒商城高级篇(38)——异步编排之商品详情查询
异步编排之商品详情查询 异步编排 CompletableFuture介绍 创建异步对象 计算完成时回调方法 handle 方法 线程串行化方法 两任务组合 全部完成 一个完成即可 多任务组合 业务描述 ...
- 【谷粒商城高级篇】商品服务 商品上架
谷粒商城笔记合集 分布式基础篇 分布式高级篇 高可用集群篇 ===简介&环境搭建=== ===Elasticsearch=== 项目简介与分布式概念(第一.二章) Elasticsearch: ...
- 【谷粒商城高级篇】商城业务:商品检索
谷粒商城笔记合集 分布式基础篇 分布式高级篇 高可用集群篇 ===简介&环境搭建=== ===Elasticsearch=== 项目简介与分布式概念(第一.二章) Elasticsearch: ...
- 【谷粒商城高级篇】Elasticsearch:全文检索
谷粒商城笔记合集 分布式基础篇 分布式高级篇 高可用集群篇 ===简介&环境搭建=== ===Elasticsearch=== 项目简介与分布式概念(第一.二章) Elasticsearch: ...
- 谷粒商城高级篇笔记1
这里写自定义目录标题 0.ElasticSearch 1.Nginx配置域名问题 01.Nginx(反向代理) 配置 02.Nginx(负载均衡)+ 网关 配置 03.Nginx动静分离 2.JMet ...
- 谷粒商城-高级篇-aiueo
105 初步检索 105.1 _cat GET /_cat/nodes : 查看所有节点 GET /_cat/health : 查看es健康状况 GET /_cat/master : 查看主节点 GE ...
- 谷粒商城高级篇爬坑笔记--错误异常信息乱码问题
由于高级篇开发相对较多,配置的内容较少,本人编写过程中没有遇到特别大的问题,唯一的问题就是消息乱码: 项目定义了如下的异常类: UNKNOW_EXCEPTION(10000,"系统未知异常& ...
最新文章
- 使用SIFT特征提取和K-Means方法对图片进行分类
- 怎么用python处理数据_Python数据清洗 - 洗什么?怎么洗?看完就明白了
- IT技术人,“三十而已”
- Python 之 Python2 和 Python3 的区别
- C语言中的strncmp
- 我和阿里巴巴的孽缘(一)
- ABBYY FineReader 12PDF选项卡之图像及文字设置
- Eclipse“ctrl+左键”链到实现类
- 链表根据主元切分成3段
- quotes 整站数据爬取存mongo
- Java 使用 OpenCV (二)之 视频编解码器
- 三层链路冗余-单宿主网络(拓扑图及思路)
- H5热门游戏模板案例解读:贪吃蛇玩法的新高度
- 如何卸载快压病毒流氓软件--不停自动下载安装App
- 给电脑C盘系统盘瘦身的四种方法
- Communications link failure错误(亲测有效)
- python入门容器-列表ListDay05
- 被迫改变生活方式对少数族群的微生物群和健康的影响
- Eclipse中mvn install 报错error in opening zip file
- jtable 表头 透明_日本艺术家携手岡本打造了一对“拥薄透明人”!为情侣们定制了一份专属浪漫!这个七夕,一起拥抱爱吧!...