谷粒商城-高级-56 -商城业务-商品详情-异步编排优化
一、顺序获取详情
商品详情获取代码:com/atguigu/gulimall/product/service/impl/SkuInfoServiceImpl.java
@Override
public SkuItemVo item(Long skuId) {
SkuItemVo skuItemVo = new SkuItemVo();
// 1、sku基本信息获取 pms_sku_info
SkuInfoEntity info = getById(skuId);
skuItemVo.setInfo(info);
Long spuId = info.getSpuId();
Long catalogId = info.getCatalogId();
//2、sku的图片信息 pms_sku_images
List<SkuImagesEntity> imagesEntities = skuImagesService.getImagesBySkuId(skuId);
skuItemVo.setImages(imagesEntities);
//3、获取spu的销售属性组合
// 分析当前spu有多少个sku(pms_sku_info),然后再查sku有多少个属性组合(pms_sku_sale_attr_value)
List<SkuItemSaleAttrVo> saleAttrVos = skuSaleAttrValueService.getSaleAttrBySpuId(spuId);
skuItemVo.setSaleAttr(saleAttrVos);
//4、获取spu的介绍 pms_spu_info_desc
SpuInfoDescEntity spuInfoDescEntity = spuInfoDescService.getById(spuId);
skuItemVo.setDesc(spuInfoDescEntity);
//5、获取spu的规格参数信息
List<SpuItemAttrGroupVo> attrGroupVos = attrGroupService.getAttrGroupWithAttrsBySpuId(spuId, catalogId);
skuItemVo.setGroupAttrs(attrGroupVos);
return skuItemVo;
}
可以看到上边的商品详情查询逻辑是按照执行顺序查询的,1查完,2才能查,2查完,3才能查,这样比较耗时,我们可以使用异步的方式来查询,上边代码的1,2是没有关系的,3、4、5必须依赖1的结果,下边就用之前学的异步编排的方式来优化代码。
二、异步编排获取详情
1、线程池配置
要在项目中使用异步编排,需要先创建线程池配置类,然后直接使用Bean。
1、创建线程池配置类com/atguigu/gulimall/product/config/MyThreadConfig.java
package com.atguigu.gulimall.product.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* @author: kaiyi
* @create: 2020-09-05 18:59
*/
// @EnableConfigurationProperties(ThreadPoolConfigProperties.class)
// 我们的配置属性已经加入到容器中了(component),所以,不再需要开启上边的属性配置了
@Configuration
public class MyThreadConfig {
@Bean
public ThreadPoolExecutor threadPoolExecutor(ThreadPoolConfigProperties pool) {
/*
这里是写死的参数,需要从配置文件里边获取相关参数
return new ThreadPoolExecutor(
20,
200,
10,
pool.getKeepAliveTime(),
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(100000),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy()
);
*/
return new ThreadPoolExecutor(
pool.getCoreSize(),
pool.getMaxSize(),
pool.getKeepAliveTime(),
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(100000),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy()
);
}
}
2、创建线程池属性类com/atguigu/gulimall/product/config/ThreadPoolConfigProperties.java
package com.atguigu.gulimall.product.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* @author: kaiyi
* @create: 2020-09-05 19:07
*/
@ConfigurationProperties(prefix = "gulimall.thread")
@Component
@Data
public class ThreadPoolConfigProperties {
private Integer coreSize;
private Integer maxSize;
private Integer keepAliveTime;
}
3、修改配置文件
添加线程池相关配置gulimall-product/src/main/resources/application.properties
spring.cache.type=redis
#spring.cache.cache-names=
spring.cache.redis.time-to-live=3600000
#
#spring.cache.redis.key-prefix=CACHE_
spring.cache.redis.use-key-prefix=true
# 空值也存入防止缓存穿透
spring.cache.redis.cache-null-values=true
# 线程池配置
gulimall.thread.core-size=20
gulimall.thread.max-size=200
gulimall.thread.keep-alive-time=10
我们可以看到,IDEA编辑器会有自定义配置类的相关属性的提示,如果没有看到,则需要添加自定义配置文件依赖。
自定义配置依赖:
pom.xml
<!-- 配置提示 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
2、代码优化
com/atguigu/gulimall/product/service/impl/SkuInfoServiceImpl.java
@Service("skuInfoService")
public class SkuInfoServiceImpl extends ServiceImpl<SkuInfoDao, SkuInfoEntity> implements SkuInfoService {
@Resource
private SkuImagesService skuImagesService;
@Resource
private SpuInfoDescService spuInfoDescService;
@Resource
private AttrGroupService attrGroupService;
@Resource
private SkuSaleAttrValueService skuSaleAttrValueService;
@Autowired
ThreadPoolExecutor threadPoolExecutor; // 线程池
/**
* 异步编排获取
*/
@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;
}, threadPoolExecutor);
// 接下来做,res表示上一步的返回值
CompletableFuture<Void> saleAttrFuture = infoFuture.thenAcceptAsync((res) -> {
//3、获取spu的销售属性组合
// 分析当前spu有多少个sku(pms_sku_info),然后再查sku有多少个属性组合(pms_sku_sale_attr_value)
List<SkuItemSaleAttrVo> saleAttrVos = skuSaleAttrValueService.getSaleAttrBySpuId(res.getSpuId());
skuItemVo.setSaleAttr(saleAttrVos);
}, threadPoolExecutor);
CompletableFuture<Void> descFuture = infoFuture.thenAcceptAsync((res) -> {
//4、获取spu的介绍 pms_spu_info_desc
SpuInfoDescEntity spuInfoDescEntity = spuInfoDescService.getById(res.getSpuId());
skuItemVo.setDesc(spuInfoDescEntity);
}, threadPoolExecutor);
CompletableFuture<Void> baseAttrFuture = infoFuture.thenAcceptAsync((res) -> {
//5、获取spu的规格参数信息
List<SpuItemAttrGroupVo> attrGroupVos = attrGroupService.getAttrGroupWithAttrsBySpuId(res.getSpuId(), res.getCatalogId());
skuItemVo.setGroupAttrs(attrGroupVos);
}, threadPoolExecutor);
CompletableFuture<Void> imageFuture = CompletableFuture.runAsync(() -> {
//2、sku的图片信息 pms_sku_images
List<SkuImagesEntity> imagesEntities = skuImagesService.getImagesBySkuId(skuId);
skuItemVo.setImages(imagesEntities);
}, threadPoolExecutor);
// 等到所有任务都完成,infoFuture 可以不用写
// CompletableFuture.allOf(infoFuture, saleAttrFuture, descFuture, baseAttrFuture, imageFuture).get();
CompletableFuture.allOf(saleAttrFuture, descFuture, baseAttrFuture, imageFuture).get();
return skuItemVo;
}
}
单元测试:
@Test
public void itemTest() throws ExecutionException, InterruptedException {
Long skuId = 1L;
SkuItemVo itemVo = skuInfoService.item(skuId);
System.out.println(itemVo);
}
测试执行结果:
2020-09-05 20:12:08.508 INFO 23284 --- [ main] c.a.n.client.config.impl.ClientWorker : [fixed-127.0.0.1_8848-748c5710-1166-498b-9e0e-528cb6c9d769] [subscribe] gulimall-product.properties+DEFAULT_GROUP+748c5710-1166-498b-9e0e-528cb6c9d769
2020-09-05 20:12:08.510 INFO 23284 --- [ main] c.a.nacos.client.config.impl.CacheData : [fixed-127.0.0.1_8848-748c5710-1166-498b-9e0e-528cb6c9d769] [add-listener] ok, tenant=748c5710-1166-498b-9e0e-528cb6c9d769, dataId=gulimall-product.properties, group=DEFAULT_GROUP, cnt=1
2020-09-05 20:12:09.274 INFO 23284 --- [pool-2-thread-1] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2020-09-05 20:12:10.144 INFO 23284 --- [pool-2-thread-1] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
2020-09-05 20:12:10.165 DEBUG 23284 --- [pool-2-thread-2] c.a.g.p.dao.SkuImagesDao.selectList : ==> Preparing: SELECT id,img_sort,img_url,default_img,sku_id FROM pms_sku_images WHERE (sku_id = ?)
2020-09-05 20:12:10.262 DEBUG 23284 --- [pool-2-thread-1] c.a.g.product.dao.SkuInfoDao.selectById : ==> Preparing: SELECT sku_id,sku_name,sku_title,catalog_id,sale_count,price,brand_id,sku_default_img,sku_subtitle,sku_desc,spu_id FROM pms_sku_info WHERE sku_id=?
2020-09-05 20:12:10.279 DEBUG 23284 --- [pool-2-thread-2] c.a.g.p.dao.SkuImagesDao.selectList : ==> Parameters: 1(Long)
2020-09-05 20:12:10.279 DEBUG 23284 --- [pool-2-thread-1] c.a.g.product.dao.SkuInfoDao.selectById : ==> Parameters: 1(Long)
2020-09-05 20:12:10.334 DEBUG 23284 --- [pool-2-thread-2] c.a.g.p.dao.SkuImagesDao.selectList : <== Total: 1
2020-09-05 20:12:10.334 DEBUG 23284 --- [pool-2-thread-1] c.a.g.product.dao.SkuInfoDao.selectById : <== Total: 1
2020-09-05 20:12:10.387 DEBUG 23284 --- [pool-2-thread-4] c.a.g.p.dao.SpuInfoDescDao.selectById : ==> Preparing: SELECT spu_id,decript FROM pms_spu_info_desc WHERE spu_id=?
2020-09-05 20:12:10.387 DEBUG 23284 --- [pool-2-thread-4] c.a.g.p.dao.SpuInfoDescDao.selectById : ==> Parameters: 5(Long)
2020-09-05 20:12:10.393 DEBUG 23284 --- [pool-2-thread-3] c.a.g.p.d.A.getAttrGroupWithAttrsBySpuId : ==> Preparing: 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 = ? AND pag.catelog_id = ?
2020-09-05 20:12:10.394 DEBUG 23284 --- [pool-2-thread-3] c.a.g.p.d.A.getAttrGroupWithAttrsBySpuId : ==> Parameters: 5(Long), 225(Long)
2020-09-05 20:12:10.394 DEBUG 23284 --- [pool-2-thread-4] c.a.g.p.dao.SpuInfoDescDao.selectById : <== Total: 1
2020-09-05 20:12:10.398 DEBUG 23284 --- [pool-2-thread-3] c.a.g.p.d.A.getAttrGroupWithAttrsBySpuId : <== Total: 1
2020-09-05 20:12:10.400 DEBUG 23284 --- [pool-2-thread-5] c.a.g.p.d.S.getSaleAttrBySpuId : ==> Preparing: 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 = ? GROUP BY ssav.attr_id, ssav.attr_name, ssav.attr_value
2020-09-05 20:12:10.400 DEBUG 23284 --- [pool-2-thread-5] c.a.g.p.d.S.getSaleAttrBySpuId : ==> Parameters: 5(Long)
2020-09-05 20:12:10.405 DEBUG 23284 --- [pool-2-thread-5] c.a.g.p.d.S.getSaleAttrBySpuId : <== Total: 1
SkuItemVo(info=SkuInfoEntity(skuId=1, spuId=5, skuName=华为P60 8G, skuDesc=null, catalogId=225, brandId=4, skuDefaultImg=https://gulimall-corwien.oss-cn-heyuan.aliyuncs.com/2020-08-26/54995f55-c35c-4711-8447-c2482336ae1e_8bf441260bffa42f.jpg, skuTitle=华为P60 8G, skuSubtitle=华为国产旗舰, price=6999.0000, saleCount=0), hasStock=true, images=[SkuImagesEntity(id=1, skuId=1, imgUrl=https://gulimall-corwien.oss-cn-heyuan.aliyuncs.com/2020-08-26/54995f55-c35c-4711-8447-c2482336ae1e_8bf441260bffa42f.jpg, imgSort=null, defaultImg=1)], saleAttr=[SkuItemSaleAttrVo(attrId=3, attrName=内存, attrValues=[AttrValueWithSkuIdVo(attrValue=8G, skuIds=1)])], desc=SpuInfoDescEntity(spuId=5, decript=https://gulimall-corwien.oss-cn-heyuan.aliyuncs.com/2020-08-26/360b82a0-3f26-48dc-8112-0923fd4fd35c_0d40c24b264aa511.jpg), groupAttrs=[SpuItemAttrGroupVo(groupName=CPU星号, attrs=[Attr(attrId=null, attrName=CPU, attrValue=麒麟800)])])
2020-09-05 20:12:10.938 INFO 23284 --- [ Thread-10] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated...
2020-09-05 20:12:11.043 INFO 23284 --- [ Thread-10] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed.
为者常成,行者常至
自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)