谷粒商城实战笔记-203-商城业务-商品详情-环境搭建

文章目录

这一部分是关于商品详情页的内容,商品详情页包含五部分的内容:

  • sku基本信息
  • sku图片信息
  • spu的销售属性
  • spu的介绍
  • spu的规格参数

由下面几集构成:

  • 203-商城业务-商品详情-环境搭建
  • 204-商城业务-商品详情-模型抽取
  • 205-商城业务-商品详情-规格参数
  • 206-商城业务-商品详情-销售属性组合
  • 207-商城业务-商品详情-详情页渲染
  • 208-商城业务-商品详情-销售属性渲染
  • 209-商城业务-商品详情-sku组合切换
  • 210-商城业务-商品详情-异步编排优化

一,页面环境搭建

1,上传详情页静态资源到nignx

使用xftp将课程提供的详情页静态资源上传到nginx的html/static/item目录。

2,拷贝详情页html模板到product模块的templates文件夹下

3,新增ItemController类

在Product模块的web包下,新增ItemController类,在其中添加详情页接口。

cpp 复制代码
@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 {
        return "item";
    }
}

二,后台接口逻辑实现

这个接口的实现,逻辑也比较复杂,一定要做好两步:

  • 先理解业务需求
  • 根据需求设计返回给前端的数据结构。

这两步完成之后,编码水到渠成。

cpp 复制代码
@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 = this.getById(skuId);
            skuItemVo.setInfo(info);
            return info;
        }, executor);


        // thenAcceptAsync 能接收到上一步的结果,但返回值
        CompletableFuture<Void> saleAttrFuture = infoFuture.thenAcceptAsync((res) -> {
            //3、获取spu的销售属性组合
            List<SkuItemSaleAttrVo> saleAttrVos = skuSaleAttrValueService.getSaleAttrBySpuId(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.setDesc(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> imagesEntities = skuImagesService.getImagesBySkuId(skuId);
            skuItemVo.setImages(imagesEntities);
        }, executor);


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

        return skuItemVo;
    }

三,全局线程池对象

在开发详情页时,我们使用了全局线程池,通过SpringBoot的自动配置装配机制:

  • ①读取配置文件中的配置,封装为属性Bean
  • ②在自动配置类中使用这个Bean对象封装的属性,创建线程池对象
  • ③将线程池对象注入到Spring容器中

第一步:定义配置属性类 ThreadPoolConfigProperties

首先,定义了一个配置属性类 ThreadPoolConfigProperties,用来存储线程池的配置信息。

该类使用了 @ConfigurationProperties 注解来绑定配置文件中的值到类的属性上。

项目启动时,扫描到带注解@ConfigurationProperties的类时,会创建一个该类的对象,读取配置文件当前相关的配置作为属性值,最后将对象注入到Spring容器中。

java 复制代码
@ConfigurationProperties(prefix = "gulimall.thread")
@Data
public class ThreadPoolConfigProperties {

    private Integer coreSize;

    private Integer maxSize;

    private Integer keepAliveTime;
}

这里指定了前缀 gulimall.thread,意味着可以通过在配置文件(如 application.ymlapplication.properties)中添加以下类似的配置项来设置线程池的参数:

yaml 复制代码
gulimall:
  thread:
    coreSize: 20
    maxSize: 200
    keepAliveTime: 10

第二步:启用配置属性绑定

为了让 Spring Boot 自动绑定这些配置,我们需要在配置类上使用 @EnableConfigurationProperties 注解,并指定配置类的类型。

java 复制代码
@EnableConfigurationProperties(ThreadPoolConfigProperties.class)
@Configuration
public class MyThreadConfig {
    // ...
}

@EnableConfigurationProperties 注解告诉 Spring 容器,当解析配置时应该激活并实例化指定的配置属性类。这意味着当 Spring Boot 启动时,它会查找带有此注解的类,并根据配置文件中的值填充这些类的属性。

第三步:创建线程池 Bean

在配置类 MyThreadConfig 中,我们通过 @Bean 方法创建了一个 ThreadPoolExecutor 实例并返回它。这将允许 Spring 容器管理这个线程池 Bean。

java 复制代码
@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()
    );
}

当 Spring 容器扫描到这个配置类时,它会执行 @Bean 方法来创建 ThreadPoolExecutor 实例。这里有几个关键点需要注意:

  1. 注入配置属性ThreadPoolConfigProperties pool 是方法参数,Spring 会自动注入配置好的 ThreadPoolConfigProperties 实例。这是因为我们在配置类上使用了 @EnableConfigurationProperties 注解。

  2. 创建线程池 :在 threadPoolExecutor 方法中,我们根据从 pool 对象获取的配置值来创建 ThreadPoolExecutor。例如,pool.getCoreSize() 返回核心线程数等。

  3. Bean 注入 :通过 @Bean 注解,Spring 容器将负责管理 ThreadPoolExecutor 的生命周期。这意味着线程池可以被其他组件注入和使用。

Spring 如何获取配置

在创建 ThreadPoolExecutor Bean 的过程中,Spring 会通过以下步骤来获取配置:

  1. 读取配置文件 :当 Spring Boot 启动时,它会读取配置文件中的配置项,并尝试与带有 @ConfigurationProperties 注解的类进行绑定。

  2. 实例化配置类 :Spring 会实例化 ThreadPoolConfigProperties 类,并使用配置文件中的值填充其属性。

  3. 注入配置对象 :当 @Bean 方法被调用时,Spring 会自动注入已经实例化并填充好的 ThreadPoolConfigProperties 对象,即 pool 参数。

  4. 创建线程池 :最后,ThreadPoolExecutor 使用从 pool 获取的配置值来初始化。

总结

通过上述步骤,可以看到 Spring Boot 是如何自动地配置线程池的。

配置文件中的值通过 @ConfigurationProperties 绑定到了 ThreadPoolConfigProperties 类中.

然后通过 @EnableConfigurationProperties@Bean 方法,Spring 容器能够自动创建并管理线程池 Bean。

这种机制极大地简化了配置过程,使得开发人员可以更加专注于业务逻辑而不是配置细节。

相关推荐
wusong9992 小时前
mongoDB回顾笔记(一)
数据库·笔记·mongodb
猫爪笔记2 小时前
前端:HTML (学习笔记)【1】
前端·笔记·学习·html
Resurgence032 小时前
【计组笔记】习题
笔记
pq113_63 小时前
ftdi_sio应用学习笔记 3 - GPIO
笔记·学习·ftdi_sio
爱米的前端小笔记3 小时前
前端八股自学笔记分享—页面布局(二)
前端·笔记·学习·面试·求职招聘
寒笙LED6 小时前
C++详细笔记(六)string库
开发语言·c++·笔记
岳不谢6 小时前
VPN技术-VPN简介学习笔记
网络·笔记·学习·华为
红色的山茶花8 小时前
YOLOv8-ultralytics-8.2.103部分代码阅读笔记-block.py
笔记·深度学习·yolo
坚硬果壳_8 小时前
《硬件架构的艺术》笔记(六):流水线的艺术
笔记·硬件架构
夜流冰10 小时前
工程师 - 智能家居方案介绍
笔记