谷粒商城实战笔记-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.yml 或 application.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。

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

相关推荐
Rabitebla5 小时前
【Linux 底层原理】进程(十):进程等待详解---从僵尸进程到 wait、waitpid 与 status
linux·c++·笔记·学习·visual studio
小lu飞7 小时前
2026小红书小工具怎么制作:纯前端 ZIP 打包、沙箱限制与笔记挂载流程
前端·笔记·ai·ai编程
无心水10 小时前
24、系统架构师论文写作专题 核心考点与学习笔记
笔记·学习·系统架构·架构师·安全架构·软考架构师·软考系统架构设计师
蒸蒸yyyyzwd11 小时前
邓明 Agent 系统面试-意图识别学习笔记
笔记·学习
Zhao-Jichao14 小时前
AI Prompting for Everyone 课程笔记 - P21 总结 Conclusion
人工智能·笔记
欢欢李14 小时前
【LTE L3 笔记 05】LTE同步信号
笔记·无线通信·物理层·lte·空口协议
La Pulga16 小时前
【FreeRTOS源码学习笔记】空闲任务与阻塞延时
笔记·mcu·学习·嵌入式·freertos·实时操作系统
蒸蒸yyyyzwd16 小时前
秋招学习笔记 day106
笔记·学习
小李不想当小白17 小时前
WDG看门狗(STM32标准库学习笔记)
笔记·stm32·单片机·嵌入式硬件·学习·嵌入式
欢欢李17 小时前
【LTE L3 笔记 04】LTE帧结构
笔记·无线通信·物理层·lte·空口协议