天机学堂项目总结(day3~day4)

目录

[Day03-02. 产品原型 - 分析业务流程](#Day03-02. 产品原型 - 分析业务流程)

[Day03-03. 产品原型.设计提交学习记录接口](#Day03-03. 产品原型.设计提交学习记录接口)

[Day03-04. 产品原型 - 设计查询学习记录接口](#Day03-04. 产品原型 - 设计查询学习记录接口)

[Day03-05. 产品原型 - 设计学习计划相关接口](#Day03-05. 产品原型 - 设计学习计划相关接口)

[Day03-06. 产品原型 - 设计数据库表结构](#Day03-06. 产品原型 - 设计数据库表结构)

[Day03-07. 开发接口 - 查询指定课程学习记录](#Day03-07. 开发接口 - 查询指定课程学习记录)

[Day03-08. 开发接口 - 提交学习记录的流程分析](#Day03-08. 开发接口 - 提交学习记录的流程分析)

[Day03-09. 开发接口 - 实现添加学习记录接口](#Day03-09. 开发接口 - 实现添加学习记录接口)

[问题:@Documented 这个注解有什么用 ?](#问题:@Documented 这个注解有什么用 ?)

问题:下图定义的自定义枚举是怎么实现功能的?

[Day03-10. 开发接口 - 测试提交学习记录接口](#Day03-10. 开发接口 - 测试提交学习记录接口)

[Day03-11. 开发接口 - 创建学习计划](#Day03-11. 开发接口 - 创建学习计划)

问题:下图注解作用?

[Day03-12. 开发接口 - 查询学习计划 - 分析代码流程](#Day03-12. 开发接口 - 查询学习计划 - 分析代码流程)

[Day03-13. 开发接口 - 查询我的学习计划 - 本周总的...](#Day03-13. 开发接口 - 查询我的学习计划 - 本周总的...)

问题:getBaseMapper()是什么?

问题:变成map的好处?

问题:SQL语句中sum和count区别?

[Day03-14 - 开发接口 - 查询我的学习计划 - 分页数据查询](#Day03-14 - 开发接口 - 查询我的学习计划 - 分页数据查询)

问题:需要sql查询返回是一个集合该怎么办?

[Day03-15. 开发接口 - 测试我的学习计划接口](#Day03-15. 开发接口 - 测试我的学习计划接口)

[Day04-01. 今日课程介绍](#Day04-01. 今日课程介绍)

[Day04-02. 方案分析 - 高并发优化方案分析](#Day04-02. 方案分析 - 高并发优化方案分析)

[Day04-03. 方案分析 - 播放进度统计优化方案](#Day04-03. 方案分析 - 播放进度统计优化方案)

问题:播放进度优化核心是哪里?

[Day04-04. 方案分析 - 播放进度统计数据持久化方案](#Day04-04. 方案分析 - 播放进度统计数据持久化方案)

[Day04-05. 方案分析 - 延迟任务](#Day04-05. 方案分析 - 延迟任务)

问题:解释Durationh个System.nanoTime()?

问题:idea生成单元测试的快捷键?

[Day04-06. 代码改造 - 添加播放记录到缓存并添加延迟任务](#Day04-06. 代码改造 - 添加播放记录到缓存并添加延迟任务)

[Day04-07. 代码改造 - 播放记录缓存的读取和清除方法](#Day04-07. 代码改造 - 播放记录缓存的读取和清除方法)

[Day04-08. 代码改造 - 异步执行延迟任务](#Day04-08. 代码改造 - 异步执行延迟任务)

问题:下图为什么要设置为null?

问题:Spring的生命周期?

[Day04-09. 代码改造 - 改造提交学习记录接口](#Day04-09. 代码改造 - 改造提交学习记录接口)

[Day04-10. 代码改造 - 测试提交学习记录接口](#Day04-10. 代码改造 - 测试提交学习记录接口)

[Day04-11. 课后思考题](#Day04-11. 课后思考题)

[问题:DelayQueue >存在的问题以及怎么优化?](#问题:DelayQueue >存在的问题以及怎么优化?)

问题:线程池怎么定义及使用?

[问题:线程池 7 大核心参数?](#问题:线程池 7 大核心参数?)


Day03-02. 产品原型 - 分析业务流程

Day03-03. 产品原型.设计提交学习记录接口

Day03-04. 产品原型 - 设计查询学习记录接口

Day03-05. 产品原型 - 设计学习计划相关接口

Day03-06. 产品原型 - 设计数据库表结构

Day03-07. 开发接口 - 查询指定课程学习记录

Day03-08. 开发接口 - 提交学习记录的流程分析

Day03-09. 开发接口 - 实现添加学习记录接口

问题:@Documented 这个注解有什么用 ?

让这个自定义注解,在生成 JavaDoc 文档时被显示出来。


具体说

  1. 它是 Java 原生的元注解(标记注解的注解)

  2. 不加 @Documented 别人用 IDEA 查看你的 @EnumValid 时,鼠标悬停、JavaDoc 里看不到这个注解

  3. 加上 @Documented 生成文档、鼠标悬浮提示时,@EnumValid 会完整显示在文档里


举个例子

你写了:

java

运行

复制代码
@Documented
public @interface EnumValid {
}

别人在使用时:

java

运行

复制代码
@EnumValid
private Integer status;

在 IDEA 鼠标悬浮、或生成 JavaDoc 时,就能看到 @EnumValid 这个注解,而不是被忽略。

问题:下图定义的自定义枚举是怎么实现功能的?

java 复制代码
/**
 * 用于状态的枚举校验
 **/
@Documented         // 生成JavaDoc时显示该注解
@Retention(RetentionPolicy.RUNTIME)  // 运行时生效
@Target({ ElementType.PARAMETER, ElementType.FIELD, ElementType.METHOD })
// 可标注在:参数、字段、方法上
@Constraint(validatedBy = {EnumValidator.class, EnumValueValidator.class})
// 真正的校验逻辑由这两个类执行:
// EnumValidator 校验枚举
// EnumValueValidator 校验数字是否在指定列表里
public @interface EnumValid { // 定义注解

    // 校验失败时的提示信息
    String message() default "不满足业务条件";

    // 允许的数字列表,例如:enumeration = {0,1,2,3}
    int[] enumeration() default {};

    // 校验分组(固定格式)
    Class<?>[] groups() default { };

    // 负载(固定格式)
    Class<? extends Payload>[] payload() { };
}
  1. @Constraint(validatedBy = ...)
  • 绑定真正做校验的类

  • 这里绑定了两个:

    • EnumValidator:校验枚举

    • EnumValueValidator:校验数字是否在指定列表

Day03-10. 开发接口 - 测试提交学习记录接口

Day03-11. 开发接口 - 创建学习计划

问题:下图注解作用?

@Range表示范围

@Valid 的作用非常核心,简单一句话就是:

让 Spring 自动校验你的 DTO 参数(LearningPlanDTO)是否合法,不合法就直接返回错误,不需要你写 if 判断。

Day03-12. 开发接口 - 查询学习计划 - 分析代码流程

Day03-13. 开发接口 - 查询我的学习计划 - 本周总的...

问题:getBaseMapper()是什么?

getBaseMapper() = 获取当前 Service 对应的 Mapper 对象 就是用来调用 Mapper 里面的自定义方法的。

问题:变成map的好处?

Map<Long, Integer> countMap = IdAndNumDTO.toMap(list);

List 转 Map 的好处(背这个就够)

一句话:为了后面循环时,不用反复查库、不用反复遍历 List,直接 O (1) 快速取值!


详细解释(结合你这段代码)

你现在的代码:

java

运行

复制代码
// 1. 查询出来是 List 结构
List<IdAndNumDTO> list = recordMapper.countLearnedSections(userId, begin, end);

// 2. 转成 Map<id, 数量>
Map<Long, Integer> countMap = IdAndNumDTO.toMap(list);

后面你要循环每一个课程 ,拿对应已学习小节数:

java

运行

复制代码
for (LearningLesson r : records) {
    // 从map里 1 步拿到值!
    vo.setWeekLearnedSections(countMap.getOrDefault(r.getId(), 0));

问题:SQL语句中sum和count区别?

  • SUM():对列的数值做加法运算,结果是「数值总和」
  • COUNT():统计行的数量,结果是「行数 / 非空值个数」
函数 作用 计算对象 空值处理
SUM(列名) 求和 :把指定列的数值累加起来 列中的数值 遇到 NULL 会自动忽略,不参与计算
COUNT(列名/*) 计数 :统计符合条件的行数 / 非空值数量 行 / 列的存在性 COUNT(列名) 忽略 NULL,COUNT(*) 统计所有行(含 NULL)

Day03-14 - 开发接口 - 查询我的学习计划 - 分页数据查询

问题:需要sql查询返回是一个集合该怎么办?

设置一个实体类接受它即可

Day03-15. 开发接口 - 测试我的学习计划接口

Day04-01. 今日课程介绍

Day04-02. 方案分析 - 高并发优化方案分析

Day04-03. 方案分析 - 播放进度统计优化方案

问题:播放进度优化核心是哪里?

要关注高频,那低频的就是第一次,因为它只有一次

Day04-04. 方案分析 - 播放进度统计数据持久化方案

Day04-05. 方案分析 - 延迟任务

问题:解释Durationh个System.nanoTime()?

java 复制代码
    public DelayTask(D data, Duration delayTime) {
        this.data = data;
        this.deadlineNanos = System.nanoTime() + delayTime.toNanos();
    }
  1. Duration 是什么?

一句话:Duration 是 Java 用来表示「一段时间」的工具类(时、分、秒、毫秒、纳秒)。

  1. System.nanoTime() 是什么?

一句话:获取系统当前的「纳秒级时间戳」,专门用来做精确计时、延迟、超时判断。

问题:idea生成单元测试的快捷键?

快速生成测试类

  1. 右键菜单 :在要生成测试类的类上右键,选择 Go To -> Test。

  2. 快捷键 :使用 Ctrl + Shift + T 直接打开创建测试类的弹框。

Day04-06. 代码改造 - 添加播放记录到缓存并添加延迟任务

Day04-07. 代码改造 - 播放记录缓存的读取和清除方法

Day04-08. 代码改造 - 异步执行延迟任务

问题:下图为什么要设置为null?

  1. 先搞懂:MyBatis-Plus updateById 的默认行为

updateById 会只更新对象中「非空字段」 ,而忽略 null 值的字段。

问题:Spring的生命周期?

Spring Bean 生命周期

Bean 从创建到销毁的整个过程,一共分这几步,按顺序背就行:

  1. 实例化通过构造方法创建 Bean 实例(相当于 new 了一个对象)。

  2. 属性填充 进行依赖注入,给 Bean 里的 @Autowired、@Value 等赋值。

  3. 执行 Aware 接口让 Bean 感知容器,比如:

    • BeanNameAware

    • BeanFactoryAware

    • ApplicationContextAware

  4. **前置处理(BeanPostProcessor#postProcessBeforeInitialization)**初始化之前的增强处理。

  5. 执行初始化方法

    1. @PostConstruct 标注的方法

    2. InitializingBean#afterPropertiesSet()

    3. XML 或注解指定的 initMethod

  6. **后置处理(BeanPostProcessor#postProcessAfterInitialization)**初始化之后的增强,AOP 代理就是在这里生成的。

  7. Bean 正常使用项目运行中被注入、被调用。

  8. 销毁容器关闭时执行:

    1. @PreDestroy

    2. DisposableBean#destroy()

    3. 指定的 destroyMethod


一句话精简版(面试口述)

Spring Bean 生命周期:实例化 → 属性注入 → Aware 感知 → 初始化前后置处理 → 初始化方法 → 正常使用 → 销毁。

Day04-09. 代码改造 - 改造提交学习记录接口

Day04-10. 代码改造 - 测试提交学习记录接口

Day04-11. 课后思考题

问题:DelayQueue<DelayTask<RecordTaskData>>存在的问题以及怎么优化?

目前我们的延迟任务执行还是单线程模式,大家将其改造为线程池模式,核心线程数与CPU核数一致即可。

问题:线程池怎么定义及使用?

① 先定义一个规范的线程池(带名字、带拒绝策略)

java 复制代码
private ThreadPoolExecutor poolExecutor;

// 静态内部类或直接定义线程工厂
private ThreadFactory threadFactory = new ThreadFactoryBuilder()
        .setNameFormat("delay-task-pool-%d")
        .build();

@PostConstruct
public void init() {
    // 1. 构造规范线程池
    poolExecutor = new ThreadPoolExecutor(
            12,
            12,
            60L,
            TimeUnit.SECONDS,
            new LinkedBlockingQueue<>(100),  // 队列放大一点
            threadFactory,                   // 命名线程工厂
            new ThreadPoolExecutor.CallerRunsPolicy()  // 更友好的拒绝策略
    );

    // 2. 用自己的线程池执行,而不是默认ForkJoinPool
    poolExecutor.execute(this::handleDelayTask);
}

② 加上优雅关闭

java 复制代码
@PreDestroy
public void destroy() {
    if (poolExecutor != null) {
        poolExecutor.shutdown();
        try {
            if (!poolExecutor.awaitTermination(60, TimeUnit.SECONDS)) {
                poolExecutor.shutdownNow();
            }
        } catch (InterruptedException e) {
            poolExecutor.shutdownNow();
        }
    }
}

问题:线程池 7 大核心参数?

java 复制代码
ThreadPoolExecutor(
    int corePoolSize,      // 核心线程数(一直存活)
    int maximumPoolSize,   // 最大线程数(核心+非核心)
    long keepAliveTime,    // 非核心线程空闲多久被回收
    TimeUnit unit,         // 时间单位
    BlockingQueue<Runnable> workQueue,  // 任务队列
    ThreadFactory threadFactory,        // 线程工厂(给线程起名字)
    RejectedExecutionHandler handler    // 拒绝策略
)

本文摘要:课程内容主要围绕学习系统开发展开,重点讲解了产品原型设计、接口开发和性能优化。Day03课程详细介绍了学习记录和计划的接口设计、数据库表结构及实现过程,包括查询/提交学习记录接口开发,并讨论了自定义枚举校验的实现原理。Day04课程聚焦高并发优化方案,特别是播放进度统计的优化策略,涉及延迟任务处理、缓存机制和MyBatis-Plus的更新行为。文章还穿插讲解了Spring生命周期、SQL函数区别等关键技术点,为构建高效学习系统提供了完整的技术方案。

相关推荐
酷炫码神1 分钟前
Day 10|Pinia 状态管理:把散落在各组件的数据,收进一个全局仓库
android·开发语言·javascript
驭渊的小故事19 分钟前
Spring AI Alibaba 实战:从maven依赖治理到声明式工具调用
java·人工智能·spring
Elastic 中国社区官方博客43 分钟前
我们如何通过 70 多个拉取请求,将 OpenTelemetry Java agent 迁移到 invokedynamic
java·大数据·开发语言·elasticsearch·搜索引擎·全文检索·es
tyn1881 小时前
记录本地安装nacos服务的方法及异常
java·开发语言
步行cgn1 小时前
Spring MVC 视图机制的核心接口与类
java·开发语言·后端·spring·mvc
y1su2 小时前
Leetcode 字符串模板
java·数据结构·算法·leetcode·职场和发展·动态规划
传奇开心果编程2 小时前
【Rust入门练中学】第5课:引用与借用
开发语言·rust·引用·编程语言理论·通用编程语言·借用
qetfw2 小时前
Bash 变量:export、位置参数与默认值展开验证
linux·开发语言·chrome·bash
电子云与长程纠缠2 小时前
UE5魂系游戏开发教程05
开发语言·学习·游戏·ui·ue5
cspttty3 小时前
2027风险管理岗准备路线:数学与应用数学如何补齐金融、SQL与Python
开发语言·python·金融