黑马天机学堂学习计划模块

news2025/1/14 3:36:37

核心功能

系统设计思路

​​​​​​​

代码分析

1. 学习记录管理

存储学习记录到 Redis

利用 Redis 缓存学习记录,减少频繁的数据库访问。

public void writeRecordCache(LearningRecord record) {
    String key = String.format("LEARNING:RECORD:%d", record.getLessonId());
    redisTemplate.opsForHash().put(key, record.getSectionId().toString(), JsonUtils.toJsonStr(record));
    redisTemplate.expire(key, Duration.ofMinutes(30)); // 设置缓存有效期
}

从 Redis 查询学习记录

如果缓存中存在学习记录,直接返回;否则查询数据库。

public LearningRecord readRecordCache(Long lessonId, Long sectionId) {
    String key = String.format("LEARNING:RECORD:%d", lessonId);
    Object recordData = redisTemplate.opsForHash().get(key, sectionId.toString());
    return recordData == null ? null : JsonUtils.parse(recordData.toString(), LearningRecord.class);
}

定时持久化学习记录

使用延迟任务模块,将学习记录从 Redis 同步到数据库。

public void persistLearningRecords() {
    List<LearningRecord> records = getAllCachedRecords();
    for (LearningRecord record : records) {
        learningRecordMapper.upsert(record);
    }
}

2. 延迟任务模块

延迟任务定义

每个任务封装了学习记录及延迟时间。

public class DelayTask<D> implements Delayed {
    private D data;
    private long deadline; // 纳秒时间戳

    @Override
    public long getDelay(TimeUnit unit) {
        return unit.convert(deadline - System.nanoTime(), TimeUnit.NANOSECONDS);
    }
}

延迟队列的处理

任务到达延迟时间后,从队列中取出并处理。

public void handleDelayTasks() {
    while (true) {
        try {
            DelayTask<RecordTaskData> task = queue.take();
            persistLearningRecords(task.getData()); // 持久化记录
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

3. 积分与排行榜管理

积分记录管理

public void addPoints(Long userId, Long courseId, int points) {
    PointsRecord record = new PointsRecord();
    record.setUserId(userId);
    record.setCourseId(courseId);
    record.setPoints(points);
    record.setCreateTime(LocalDateTime.now());
    pointsRecordMapper.insert(record);
}

每日积分统计

public List<PointsStatisticsVO> queryMyPointsToday(Long userId) {
    LocalDate today = LocalDate.now();
    return pointsRecordMapper.findByUserIdAndDate(userId, today);
}

动态表名的排行榜

通过 MyBatis 的 DynamicTableNameInnerInterceptor 实现动态表名替换。

map.put("points_board", (sql, tableName) -> {
    String seasonId = getCurrentSeason();
    return tableName + "_" + seasonId; // 动态拼接表名
});

4. 互动问答模块

提问功能

public void saveQuestion(QuestionFormDTO questionDTO) {
    Question question = new Question();
    question.setContent(questionDTO.getContent());
    question.setUserId(questionDTO.getUserId());
    question.setCourseId(questionDTO.getCourseId());
    question.setCreateTime(LocalDateTime.now());
    questionMapper.insert(question);
}

管理员隐藏问题

public void hiddenQuestionAdmin(Long id, Boolean hidden) {
    Question question = questionMapper.selectById(id);
    question.setHidden(hidden);
    questionMapper.updateById(question);
}

点赞功能

使用 Redis 实现快速计数,同时支持异步更新到数据库。

public void likeQuestion(Long questionId, Long userId) {
    String redisKey = String.format("QUESTION:LIKE:%d", questionId);
    redisTemplate.opsForSet().add(redisKey, userId.toString());
}

5. Redis 缓存机制

学习记录缓存

redisTemplate.opsForHash().put("LEARNING:RECORD:123", "section_456", recordData);
redisTemplate.expire("LEARNING:RECORD:123", Duration.ofMinutes(30));

签到记录缓存

redisTemplate.opsForValue().set("SIGN:USER:123:2025-01-09", true, Duration.ofDays(1));

6. 动态表名管理

• 配置 MyBatis 的动态表名拦截器:

@Bean
public DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor() {
    Map<String, TableNameHandler> map = new HashMap<>();
    map.put("points_board", (sql, tableName) -> {
        String seasonId = getCurrentSeason();
        return tableName + "_" + seasonId;
    });
    return new DynamicTableNameInnerInterceptor(map);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2276271.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

初学stm32 --- DAC输出三角波和正弦波

输出三角波实验简要&#xff1a; 1&#xff0c;功能描述 通过DAC1通道1(PA4)输出三角波&#xff0c;然后通过DS100示波器查看波形 2&#xff0c;关闭通道1触发(即自动) TEN1位置0 3&#xff0c;关闭输出缓冲 BOFF1位置1 4&#xff0c;使用12位右对齐模式 将数字量写入DAC_…

专题 - STM32

基础 基础知识 STM所有产品线&#xff08;列举型号&#xff09;&#xff1a; STM产品的3内核架构&#xff08;列举ARM芯片架构&#xff09;&#xff1a; STM32的3开发方式&#xff1a; STM32的5开发工具和套件&#xff1a; 若要在电脑上直接硬件级调试STM32设备&#xff0c;则…

25年无人机行业资讯 | 1.1 - 1.5

25年无人机行业资讯 | 1.1 - 1.5 中央党报《经济日报》刊文&#xff1a;低空经济蓄势待发&#xff0c;高质量发展需的平衡三大关系 据新华网消息&#xff0c;2025年1月3日&#xff0c;中央党报《经济日报》发表文章指出&#xff0c;随着国家发展改革委低空经济发展司的成立&a…

时序数据库InfluxDB—介绍与性能测试

目录 一、简述 二、主要特点 三、基本概念 1、主要概念 2、保留策略 3、连续查询 4、存储引擎—TSM Tree 5、存储目录 四、基本操作 1、Java-API操作 五、项目中的应用 六、单节点的硬件配置 七、性能测试 1、测试环境 2、测试程序 3、写入测试 4、查询测试 一…

计算机网络 (35)TCP报文段的首部格式

前言 计算机网络中的TCP&#xff08;传输控制协议&#xff09;报文段的首部格式是TCP协议的核心组成部分&#xff0c;它包含了控制TCP连接的各种信息和参数。 一、TCP报文段的结构 TCP报文段由首部和数据两部分组成。其中&#xff0c;首部包含了控制TCP连接的各种字段&#xff…

GelSight Mini视触觉传感器凝胶触头升级:增加40%耐用性,拓展机器人与触觉AI 应用边界

马萨诸塞州沃尔瑟姆-2025年1月6日-触觉智能技术领军企业Gelsight宣布&#xff0c;旗下Gelsight Mini视触觉传感器迎来凝胶触头的更新。经内部测试&#xff0c;新Gel凝胶触头耐用性提升40%&#xff0c;外观与触感与原凝胶触头保持一致。此次升级有效满足了客户在机器人应用中对设…

burpsiute的基础使用(2)

爆破模块&#xff08;intruder&#xff09;&#xff1a; csrf请求伪造访问&#xff08;模拟攻击&#xff09;: 方法一&#xff1a; 通过burp将修改&#xff0c;删除等行为的数据包压缩成一个可访问链接&#xff0c;通过本地浏览器访问&#xff08;该浏览器用户处于登陆状态&a…

【ASP.NET学习】ASP.NET MVC基本编程

文章目录 ASP.NET MVCMVC 编程模式ASP.NET MVC - Internet 应用程序创建MVC web应用程序应用程序信息应用程序文件配置文件 用新建的ASP.NET MVC程序做一个简单计算器1. **修改视图文件**2. **修改控制器文件** 用新建的ASP.NET MVC程序做一个复杂计算器1.创建模型&#xff08;…

Git 命令代码管理详解

一、Git 初相识&#xff1a;版本控制的神器 在当今的软件开发领域&#xff0c;版本控制如同基石般重要&#xff0c;而 Git 无疑是其中最耀眼的明珠。它由 Linus Torvalds 在 2005 年创造&#xff0c;最初是为了更好地管理 Linux 内核源代码。随着时间的推移&#xff0c;Git 凭借…

OpenCV实现基于交叉双边滤波的红外可见光融合算法

1 算法原理 CBF是*Cross Bilateral Filter(交叉双边滤波)*的缩写&#xff0c;论文《IMAGE FUSION BASED ON PIXEL SIGNIFICANCE USING CROSS BILATERAL FILTER》。 论文中&#xff0c;作者使用交叉双边滤波算法对原始图像 A A A&#xff0c; B B B 进行处理得到细节&#xff0…

项目实战--网页五子棋(用户模块)(1)

接下来我将使用Java语言&#xff0c;和Spring框架&#xff0c;实现一个简单的网页五子棋。 主要功能包括用户登录注册&#xff0c;人机对战&#xff0c;在线匹配对局&#xff0c;房间邀请对局&#xff0c;积分排行版等。 这篇文件讲解用户模块的后端代码 1. 用户表与实体类 …

机器学习之随机森林算法实现和特征重要性排名可视化

随机森林算法实现和特征重要性排名可视化 目录 随机森林算法实现和特征重要性排名可视化1 随机森林算法1.1 概念1.2 主要特点1.3 优缺点1.4 步骤1.5 函数及参数1.5.1 函数导入1.5.2 参数 1.6 特征重要性排名 2 实际代码测试 1 随机森林算法 1.1 概念 是一种基于树模型的集成学…

MySQL存储引擎、索引、索引失效

MySQL Docker 安装 MySQL8.0&#xff0c;安装见docker-compose.yaml 操作类型 SQL 程序语言有四种类型&#xff0c;对数据库的基本操作都属于这四种类&#xff0c;分为 DDL、DML、DQL、DCL DDL(Dara Definition Language 数据定义语言)&#xff0c;是负责数据结构定义与数据…

WPF基础(1.1):ComboBox的使用

本篇文章介绍ComboBox的基本使用。 本篇文章的例子实现的功能&#xff1a;后端获取前端复选框中的选项之后&#xff0c;点击“确定”按钮&#xff0c;弹出一个MessageBox&#xff0c;显示用户选择的选项。 文章目录 1. 效果展示2. 代码逻辑2.1 前端代码2.2 后端代码 1. 效果展…

前端炫酷动画--文字(二)

目录 一、弧形边框选项卡 二、零宽字符 三、目录滚动时自动高亮 四、高亮关键字 五、文字描边 六、按钮边框的旋转动画 七、视频文字特效 八、立体文字特效让文字立起来 九、文字连续光影特效 十、重复渐变的边框 十一、磨砂玻璃效果 十二、FLIP动画 一、弧形边框…

android 官网刷机和线刷

nexus、pixel可使用google官网线上刷机的方法。网址&#xff1a;https://flash.android.com/ 本文使用google线上刷机&#xff0c;将Android14 刷为Android12 以下是失败的线刷经历。 准备工作 下载升级包。https://developers.google.com/android/images?hlzh-cn 注意&…

25/1/12 嵌入式笔记 学习esp32

了解了一下位选线和段选线的知识&#xff1a; 位选线&#xff1a; 作用&#xff1a;用于选择数码管的某一位&#xff0c;例如4位数码管的第1位&#xff0c;第2位&#xff09; 通过控制位选线的电平&#xff08;高低电平&#xff09;&#xff0c;决定当前哪一位数码管处于激活状…

探秘block原理

01 概述 在iOS开发中&#xff0c;block大家用的都很熟悉了&#xff0c;是iOS开发中闭包的一种实现方式&#xff0c;可以对一段代码逻辑进行封装&#xff0c;使其可以像数据一样被传递、存储、调用&#xff0c;并且可以保存相关的上下文状态。 很多block原理性的文章都比较老&am…

【Docker】入门教程

目录 一、Docker的安装 二、Docker的命令 Docker命令实验 1.下载镜像 2.启动容器 3.修改页面 4.保存镜像 5.分享社区 三、Docker存储 1.目录挂载 2.卷映射 四、Docker网络 1.容器间相互访问 2.Redis主从同步集群 3.启动MySQL 五、Docker Compose 1.命令式安装 …

Bootstrap 前端 UI 框架

Bootstrap官网&#xff1a;Bootstrap中文网 铂特优选 Bootstrap 下载 点击进入中文文档 点击下载 生产文件是开发响应式网页应用&#xff0c;源码是底层逻辑代码&#xff0c;因为是要制作响应式网页&#xff0c;所以下载开发文件 引入 css 文件&#xff0c; bootstrap.css 和 …