news 2026/9/5 17:59:07

SpringBoot3+Vue3+MySQL智能课程学习系统全栈实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SpringBoot3+Vue3+MySQL智能课程学习系统全栈实战

这次我们来看一个完整的全栈实战项目:智能课程学习系统。技术栈就是标题里写的那一套,Java 后端 + SpringBoot3 + Vue.js3 前端 + MySQL 数据库。不做单体演示项目,而是按真实业务场景拆解功能模块、数据库设计和接口开发,适合正在准备 Java 全栈简历项目的开发者,也适合想把在线课程、学习进度统计、智能推荐这些功能落到代码里的同学。

做这类系统之前,先想清楚一个问题:它到底“智能”在哪里?很多项目把“智能”做成噱头,最后就是普通的 CRUD。这个项目里可以落地的智能点有三个:学习进度自动追踪与预警、课程内容与学员水平匹配推荐、学情数据可视化分析。这三个点分别对应后端定时任务、改进的协同过滤或规则推荐、MySQL 聚合统计与前端图表展示,每一步都有实际代码可写,也能在简历上讲清楚。

本文会把这个系统从需求拆解、数据库建表、SpringBoot3 核心接口、Vue3 页面联调到服务器部署完整串一遍。因为 Java Web 项目不涉及显卡资源,运行的资源占用重点会放在后端 JVM、MySQL 连接和前端打包产物上。你最后拿到的是一套能跑通注册登录、课程浏览、章节学习、学习进度记录、统计分析的小型学习平台,而不是只能看界面的 Demo。

1. 智能课程学习系统核心能力速览

先把项目基础信息列出来,方便快速判断这套技术路线适不适合自己。

能力项说明
项目类型前后端分离的在线课程学习管理系统
后端技术Java 17+、SpringBoot3、Spring Security、MyBatis-Plus 或 Spring Data JPA
前端技术Vue3、Vite、TypeScript、Element Plus、Pinia、Vue Router
数据库MySQL 8.0 及以上版本
核心功能用户注册登录、课程分类、课程章节管理、学习记录打卡、课程收藏、考试答题、学情统计
智能能力学习进度追踪、学习预警、基于标签匹配的课程推荐、学习时长统计
运行环境Windows、Linux 均可,推荐 2核4G 以上的云服务器或本地虚拟机
启动方式后端 mvn spring-boot:run 或打成 jar 运行,前端 npm run dev / npm run build + Nginx
API 支持RESTful API,统一返回 JSON,前后端通过接口联调
批量任务后端定时任务生成学习报告、处理过期课程状态、批量导入题库
适合场景Java 全栈练手、毕业设计、小范围企业内训系统、在线教育系统原型

这套技术栈的商业项目也在大量使用,不是那种“纯学习玩具”。SpringBoot3 相比旧版最大的变化是强制要求 Java 17,很多旧的 SSM 笔记在 SpringBoot3 上跑不通,正好可以借这个项目把新版本依赖和配置习惯梳理清楚。Vue3 端则建议直接用<script setup>写法,开发体验和代码量都优于 Vue2 写法。MySQL 侧重点则放在表结构设计、索引和统计 SQL 上。

2. 需求拆解与适用场景

2.1 角色设计

系统至少分成三种角色,复杂程度刚好覆盖全栈实践覆盖面:

  • 管理员/讲师:维护课程分类、课程信息、章节内容、试题库,查看整体学情。
  • 学员:注册登录、浏览课程、报名选课、逐章学习、提交学习进度、参与测试、查看学习报告。
  • 系统:定时统计学习数据,根据学员常学方向或填写标签推荐课程,对长时间未学习的学员发送预警。

这个角色模型已经足够用于面试讲解。如果想控制开发量,第一阶段可以先做“学员 + 讲师”两种角色,管理员能力放到讲师角色里。用户表加一个role字段,然后借助 Spring Security 的注解控制接口权限就可以。

2.2 核心业务流程

一段完整业务链路是:学员注册并登录,进入课程列表页,按分类筛选课程,点击课程序章,前端向后端提交学习进度(比如学完了第几章节、看了多长时间、是否正确完成课时),后端把数据写入学习记录表,同时把累计学习时长和最新章节同步到用户学习总表。管理员每天通过定时任务统计最近 7 天活跃学员,对连续 3 天未学习的报名学员生成“学习动力不足”预警记录。

学习记录不是一个无意义的insert,而是整个“学情智能分析”的数据底座。保存时需要考虑同一章节重复学习的覆盖策略、多条记录的时间边界、并发重复提交的问题。这一块的接口设计比普通增删改查更能体现工程能力。

2.3 适用边界与合规提醒

这类系统适合企业内部培训、学校课程管理、个人全栈开发练习,不建议在没有课程版权授权的情况下上传商业付费课程视频。如果涉及真实学员信息,需要做好敏感数据加密存储和最小权限访问。视频、试题、讲义等素材都应该确认授权范围后再投入生产环境,学习系统后台最好保留内容审核和下架入口。这些边界问题在答辩和简历项目里也经常被问到,提前设计好是加分项。

3. 总体架构与目录规划

这个项目采用前后端分离架构。用户浏览器访问 Vue3 单页应用,页面请求统一走 HTTP 到后端 REST API,后端由 SpringBoot3 处理业务逻辑和数据持久化,数据存储在 MySQL。生产环境通常在 Vue 构建产物前面加一层 Nginx,Nginx 托管静态文件并把/api/前缀请求反向代理到 Java 服务。

前端目录和后端建议分成两个总的根目录存放,比如course-frontendcourse-backend。这样在 IDEA 里导入时更清晰,部署时也方便分别打包。

后端建议包结构:

com.example.course ├── common // 通用返回结果、全局异常处理、工具类 ├── config // Security、MyBatis-Plus 分页插件、跨域配置 ├── controller // 控制器层 ├── service // 业务层 │ └── impl ├── mapper // 数据访问层 ├── entity // 实体类 ├── dto // 接收前端参数的 Data Transfer Object ├── vo // 返回前端数据的 View Object ├── task // 定时统计任务 └── CourseApplication.java

前端建议采用views/按业务页面拆分:

src ├── api // axios 请求封装 ├── assets // 静态资源 ├── components // 通用组件 ├── router // 路由配置 ├── stores // Pinia 状态 ├── views │ ├── login │ ├── course │ ├── learn │ ├── admin │ └── dashboard ├── utils └── App.vue

目录规划本身不是花架子。日常开发里,dtovo分开能避免把数据库字段直接暴露给前端,common里的统一返回结构能保证前端 axios 拦截器只处理一种数据格式。做这个项目时建议从一开始就坚持这种分层,不要图快把所有代码堆在 Controller 里。

4. MySQL 数据库设计与初始化

数据库设计是课程学习系统的核心,表结构设计得好,后面的统计逻辑会顺畅很多。这里先给出一套可直接落地的 6 张核心表设计思路。

4.1 核心表结构

用户表sys_user

CREATE TABLE sys_user ( id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '主键', username VARCHAR(50) NOT NULL UNIQUE COMMENT '登录名', password VARCHAR(100) NOT NULL COMMENT 'BCrypt 加密密码', nickname VARCHAR(50) DEFAULT '' COMMENT '昵称', role VARCHAR(20) NOT NULL DEFAULT 'STUDENT' COMMENT '角色:ADMIN/TEACHER/STUDENT', phone VARCHAR(20) DEFAULT NULL, email VARCHAR(100) DEFAULT NULL, status TINYINT DEFAULT 1 COMMENT '1启用 0禁用', created_time DATETIME DEFAULT CURRENT_TIMESTAMP, update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';

课程表course

CREATE TABLE course ( id BIGINT PRIMARY KEY AUTO_INCREMENT, title VARCHAR(200) NOT NULL COMMENT '课程名称', category_id BIGINT NOT NULL COMMENT '分类ID', cover_url VARCHAR(255) DEFAULT '' COMMENT '封面图', summary TEXT COMMENT '课程简介', difficulty TINYINT DEFAULT 1 COMMENT '难度:1入门 2进阶 3高级', teacher_id BIGINT NOT NULL, status TINYINT DEFAULT 0 COMMENT '0草稿 1上架 2下架', created_time DATETIME DEFAULT CURRENT_TIMESTAMP, update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, KEY idx_category_status (category_id, status) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='课程表';

章节表course_chapter

CREATE TABLE course_chapter ( id BIGINT PRIMARY KEY AUTO_INCREMENT, course_id BIGINT NOT NULL, chapter_no INT NOT NULL COMMENT '章节顺序', title VARCHAR(200) NOT NULL, video_url VARCHAR(255) DEFAULT '' COMMENT '视频地址', content TEXT COMMENT '讲义或正文', duration INT DEFAULT 0 COMMENT '预计学习分钟数', is_free TINYINT DEFAULT 0, created_time DATETIME DEFAULT CURRENT_TIMESTAMP, KEY idx_course_no (course_id, chapter_no) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='课程章节表';

学习记录表study_record是最关键的一张业务表:

CREATE TABLE study_record ( id BIGINT PRIMARY KEY AUTO_INCREMENT, user_id BIGINT NOT NULL, course_id BIGINT NOT NULL, chapter_id BIGINT NOT NULL, duration_seconds INT DEFAULT 0 COMMENT '本次学习时长(秒)', finish_flag TINYINT DEFAULT 0 COMMENT '是否完成本章:0否 1是', study_date DATE NOT NULL COMMENT '学习日期', created_time DATETIME DEFAULT CURRENT_TIMESTAMP, KEY idx_user_course_date (user_id, course_id, study_date), KEY idx_course_date (course_id, study_date) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='学习记录表';

再配合课程收藏表course_favorite、测试记录表exam_record,就能基本覆盖完整课程学习闭环。

4.2 MySQL 中容易踩的坑

关于 MySQL 本身有一个高频面试点:int(5)并不是限制存 5 位整数,它只是配合ZEROFILL的显示宽度,真正决定整数存储范围的是int本身。建表时不要指望把int(5)当长度约束用。

统计每个学员最近 7 天每天学习总时长时,会用到行转列的逻辑,把study_date作为动态列名,把duration_seconds聚合起来,这种统计适合先写普通分组查询,再在 Java 或前端完成行转列展示,避免直接拼复杂动态 SQL。

Navicat 连接 MySQL 如果报20021045,优先检查 MySQL 服务有没有启动、账号密码有没有写错、连接地址是不是localhost而不是写成远程端口。8.0 以上版本默认认证插件是caching_sha2_password,老版本驱动连接时会报认证错误,建议用较新的 mysql-connector-j 版本。

4.3 初始化测试数据

首次跑通项目时可以插入少量课程和章节用于联调。用户密码字段在生产里需要存 BCrypt 加密后的值,可以写一个临时接口或测试类生成密文,不要直接明文入库。

INSERT INTO sys_user (username, password, nickname, role) VALUES ('admin', '$2a$10$7JB720uK7q5FQ6fX5xKZcO6VabQJj8WZc4W8n8vV5YF6uXG9aA9uS', '管理员', 'ADMIN');

如果使用 Spring Security,启动项目前保证用户表里有可登录账号,否则会因为认证数据为空导致登录接口一直返回 401。

5. SpringBoot3 后端开发与实现

5.1 Maven 依赖配置

SpringBoot3 默认使用 Java 17,因此本机需要先安装 JDK 17 并配置好JAVA_HOME环境变量。如果下载完项目后启动报cannot access class sun.misc.Unsafeinvalid source release: 17,大概率是 JDK 版本不对或者 IDEA 的 Project SDK 没有切换到 17。

<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.2.5</version> <relativePath/> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-spring-boot3-starter</artifactId> <version>3.5.7</version> </dependency> <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> </dependencies>

版本号可能不是最新的,实际开发时建议以 Maven 仓库里的正式稳定版本为准。SpringBoot3 对 Security 6 的配置方式和 SpringBoot2 差别很大,很多网上旧配置直接拷过来会报错,遇到问题时优先查 Spring Security 6 迁移文档。

5.2 全局响应结构与异常处理

前端每次请求后端,最好约定同一个结构。定义个Result<T>,里面放 code、message、data。这样 axios 响应拦截器只用解析一层格式,前端判断逻辑会非常简单。全局异常处理使用@RestControllerAdvice,把参数校验异常、业务异常、系统异常分别处理,避免服务端异常堆栈直接抛给前端。

@Data public class Result<T> { private Integer code; private String message; private T data; public static <T> Result<T> ok(T data) { Result<T> result = new Result<>(); result.setCode(200); result.setMessage("success"); result.setData(data); return result; } public static <T> Result<T> fail(String message) { Result<T> result = new Result<>(); result.setCode(500); result.setMessage(message); return result; } }

Controller 里不要直接返回裸对象,而是返回Result。这能减少前端联调时出现类型对不上的问题。

5.3 学习进度上报接口

这是系统里最核心的业务接口。前端在学员打开某一章节、离开章节页或播放结束时调用上报接口。上报接口接收 userId、courseId、chapterId、durationSeconds、finishFlag。后端先判断该课程是否已报名、该章节是否属于课程,再写入study_record。为了避免重复点击造成大量重复数据,可以加一层约束:同一天、同一用户、同一章节,如果存在记录,则累加学习时长而不是新增。

Service 层的关键逻辑:

@Service @RequiredArgsConstructor public class StudyRecordServiceImpl implements StudyRecordService { private final StudyRecordMapper studyRecordMapper; private final CourseChapterMapper chapterMapper; @Override @Transactional(rollbackFor = Exception.class) public StudyRecordVO reportProgress(StudyRecordDTO dto) { CourseChapter chapter = chapterMapper.selectById(dto.getChapterId()); if (chapter == null || !chapter.getCourseId().equals(dto.getCourseId())) { throw new BizException("章节不存在或课程不匹配"); } StudyRecord record = studyRecordMapper.selectOne(new LambdaQueryWrapper<StudyRecord>() .eq(StudyRecord::getUserId, dto.getUserId()) .eq(StudyRecord::getCourseId, dto.getCourseId()) .eq(StudyRecord::getChapterId, dto.getChapterId()) .eq(StudyRecord::getStudyDate, LocalDate.now())); if (record == null) { record = new StudyRecord(); record.setUserId(dto.getUserId()); record.setCourseId(dto.getCourseId()); record.setChapterId(dto.getChapterId()); record.setStudyDate(LocalDate.now()); record.setDurationSeconds(dto.getDurationSeconds()); record.setFinishFlag(dto.getFinishFlag()); studyRecordMapper.insert(record); } else { if (dto.getFinishFlag() != null && dto.getFinishFlag() == 1) { record.setFinishFlag(1); } record.setDurationSeconds(record.getDurationSeconds() + dto.getDurationSeconds()); studyRecordMapper.updateById(record); } return StudyRecordVO.builder() .todaySeconds(studyRecordMapper.selectTodaySeconds(dto.getUserId(), LocalDate.now())) .build(); } }

注意@Transactional加在需要多表写入或者先查后写这种复合操作上。如果一个接口只有单表简单插入,加事务没太大意义,还容易撑大事务范围。

5.4 Spring Security 登录认证

SpringBoot3 中 Spring Security 6 的默认配置会用HttpSecurity配置安全过滤链。登录接口通常放行,其余以/api/admin/开头的接口限制管理员权限即可。

@Configuration @EnableWebSecurity @RequiredArgsConstructor public class SecurityConfig { private final UserDetailsService userDetailsService; @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http.csrf(AbstractHttpConfigurer::disable) .cors(Customizer.withDefaults()) .authorizeHttpRequests(auth -> auth .requestMatchers("/api/auth/login", "/api/public/**").permitAll() .requestMatchers("/api/admin/**").hasRole("ADMIN") .anyRequest().authenticated()) .formLogin(AbstractHttpConfigurer::disable) .httpBasic(AbstractHttpConfigurer::disable) .userDetailsService(userDetailsService); return http.build(); } }

认证通过后,Spring Security 会向 SecurityContext 写入用户信息,后续通过@AuthenticationPrincipal获取当前用户。这样做的好处是所有 Controller 不需要自己从 Token 里解析 userId。

6. Vue3 前端项目搭建与接口联调

6.1 Vite 创建与插件安装

前端项目推荐直接用 Vite 创建:

npm create vite@latest course-frontend -- --template vue-ts cd course-frontend npm install npm install axios pinia vue-router element-plus

安装完成后在main.ts中注册 Element Plus 和 Pinia。Element Plus 对 Vue3 的原生支持很好,组件风格适合后台管理类系统。

6.2 API 请求封装

前端请求后端接口时,一定不要在每页面直接散着写axios.get。统一在src/api/request.ts里创建实例,配置 baseURL、超时时间和请求拦截器。

import axios from 'axios' import { ElMessage } from 'element-plus' import { useUserStore } from '@/stores/user' const request = axios.create({ baseURL: '/api', timeout: 15000 }) request.interceptors.request.use(config => { const userStore = useUserStore() if (userStore.token) { config.headers.Authorization = `Bearer ${userStore.token}` } return config }) request.interceptors.response.use( response => { const res = response.data if (res.code !== 200) { ElMessage.error(res.message || '请求失败') return Promise.reject(new Error(res.message)) } return res.data }, error => { ElMessage.error(error.response?.data?.message || '服务异常') return Promise.reject(error) } ) export default request

开发环境调试时,Vite 的 dev server 需要配置代理,把/api转发到 SpringBoot 的 8080 端口:

server: { port: 5173, proxy: { '/api': { target: 'http://localhost:8080', changeOrigin: true } } }

这样前端开发环境访问/api/course/list,就会自动代理到后端http://localhost:8080/api/course/list,避免开发阶段跨域问题。

6.3 课程列表与学习页

课程列表页最典型的一个交互是:页面上显示筛选分类、分页数据。调用后端接口时的入参包括 page、pageSize、categoryId、keyword。Vue 组件里把筛选条件放成响应式数据,点击查询时调用接口并重置页码到 1。

学习页是学员进入某一门课程后的主场景,右侧显示章节树,点击章节标题后通过视频组件或富文本展示章节内容,页面组件监听播放时间变化,每 15 秒上报一次进度,离开页面时再上报一次最终进度。这里要注意组件卸载时上报是异步请求,页面关闭时可能请求还没发出,最好用navigator.sendBeacon或者降低上报频率来处理在线学习系统的常见问题。

6.4 路由守卫

没有登录的用户访问课程学习页面时,需要强制跳转到登录页。在 router 的beforeEach里判断 token 是否存在于 Pinia store。生产环境 token 建议使用 localStorage 持久化,刷新后通过store重新初始化恢复。

router.beforeEach((to, _from, next) => { const userStore = useUserStore() if (to.meta.requiresAuth && !userStore.token) { next({ path: '/login', query: { redirect: to.fullPath } }) } else { next() } })

Vue3 的computedwatch在这一类业务中非常实用。比如课程封面地址根据用户角色显示不同的按钮,学习进度数据变化后自动更新课程卡片上的百分比,这些都是面试时能顺手讲的响应式细节。

7. 智能学习模块与学情统计实现

7.1 基于学习记录计算课程完成度

要判断学员是否学完某门课程,最简单的方法是统计该学员在该课程下完成的学习章节数占总章节数的比例。SQL 逻辑是查出该课程总章节数,再查出该学员已经完成章节的数量,两者相除得到百分比。

SELECT c.id AS courseId, c.title AS courseTitle, COUNT(ch.id) AS totalChapter, COUNT(CASE WHEN sr.finish_flag = 1 AND sr.user_id = #{userId} THEN 1 END) AS finishedChapter FROM course c JOIN course_chapter ch ON ch.course_id = c.id LEFT JOIN study_record sr ON sr.chapter_id = ch.id WHERE c.id = #{courseId} GROUP BY c.id, c.title

这种统计结果可以作为课程列表中进度条的显示数据,也可以驱动课程结业判断逻辑。

7.2 学习预警与定时任务

预警的规则可以设计成:报名某门课程后,如果学员连续 3 天没有产生新的study_record数据,系统生成一条预警。这里需要查询最近学习日期和当前日期的差。

SELECT user_id, course_id, MAX(study_date) AS lastStudyDate FROM study_record WHERE user_id = #{userId} GROUP BY user_id, course_id

定时任务用 Spring 自带的@Scheduled即可,不需要引入额外框架。每天凌晨 1 点执行一次扫描,扫描结果写入预警表,前端在登录后的首页展示待处理预警数量。

7.3 课程推荐

推荐算法可以先用规则版实现:给用户表增加interest_tags字段,课程表增加tags字段,推荐时优先选择用户未报名、状态为上架、课程标签匹配度最高的一批课程。如果面试时想往深度学习方向讲,可以把用户学习历史行为向量化,后续替换成向量检索或其他推荐策略。但作为全栈项目,先跑通规则版本,代码清晰且可解释性强,比硬套一个跑不动的算法更有说服力。

前端首页可以命名为“为你推荐”,后端提供一个/api/course/recommend接口,只返回 6 条课程数据。数据来源是先取用户标签匹配度较高的课程,再用最近热门课程补足。这样智能模块就有了:有推荐逻辑、有学习反馈、有统计闭环,不是空壳。

8. 项目部署与接口验证

8.1 后端打包与运行

在本地开发并测试完毕后,后端项目打包成 jar:

mvn clean package -DskipTests

生成的target/course-system-0.0.1-SNAPSHOT.jar可以通过命令启动:

java -jar course-system-0.0.1-SNAPSHOT.jar --spring.profiles.active=prod

生产环境建议把数据库地址、密码等配置放到application-prod.yml里,避免直接修改代码。启动时留意JAVA_HOME是否已配置正确,以及 8080 端口是否被占用。

8.2 前端构建与 Nginx 托管

前端项目执行构建后生成dist目录:

npm run build

dist目录放到 Nginx 的 html 路径下,并在 Nginx 配置里增加前端路由回退和 API 反向代理:

server { listen 80; server_name your-domain.com; root /opt/course-frontend/dist; index index.html; location /api/ { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } location / { try_files $uri $uri/ /index.html; } }

try_files是为了让 Vue Router 使用 history 模式时,页面刷新不会出现 404。这一行对于前后端分离项目非常关键。

8.3 接口验证

启动后端后可以用 curl 快速验证服务状态:

curl http://localhost:8080/api/public/course/list

如果返回包含codemessagedata的 JSON 结构,说明后端服务正常。登录接口则使用 POST 请求提交 JSON 数据:

curl -X POST http://localhost:8080/api/auth/login \ -H "Content-Type: application/json" \ -d '{"username":"admin","password":"123456"}'

正常登录后返回的响应里会有 token,拿到 token 后再请求课程管理接口时放在Authorization: Bearer xxx请求头里。

8.4 一键运行脚本

为了本地开发方便,可以在项目根目录放两个脚本。start-dev.bat负责先启动 MySQL 服务,再分别启动后端和前端,但前后端依赖本机 IDE 的情况不建议强行自动化。后端启动脚本只需要封装 Maven 命令:

cd course-backend mvn spring-boot:run -Dspring-boot.run.profiles=dev

前端启动:

cd course-frontend npm run dev

正常情况下浏览器访问http://localhost:5173即可进入系统。如果页面空白且控制台报网络错误,先看后端服务是否真正启动,再检查前端代理配置。

9. 资源占用与性能观察

这类 Java Web 系统虽然不需要“显卡显存”,但资源占用同样需要关注。后端 SpringBoot3 项目启动后 JVM 默认堆内存可能达到物理内存的四分之一,如果服务器只有 2G 内存,启动多个服务时很容易触发java: outofmemoryerror: insufficient memory。建议手动指定 JVM 参数:

java -Xms256m -Xmx512m -jar course-system-0.0.1-SNAPSHOT.jar

观察后端进程内存和 CPU 时,使用常见命令:

# 查看 Java 进程 jps -l # 查看系统内存 free -h # 查看进程 CPU 和内存占用 top -p $(pgrep -f course-system)

MySQL 资源占用主要体现在连接数和慢查询。开发阶段连接数不会太高,但并发上来后要确定连接池上限不要超过 MySQL 的max_connections。通过慢查询日志可以排查统计 SQL 的性能问题。

SHOW VARIABLES LIKE 'slow_query_log'; SHOW VARIABLES LIKE 'long_query_time';

学习记录表的数据量会随着时间线性增长,统计学情时如果直接全表扫描,会越来越慢,务必给常用条件建立复合索引。索引文件也会占用磁盘空间,学习系统的课程视频不要直接存 MySQL,视频文件放对象存储或独立静态目录,数据表只存访问 URL。

前端性能主要关注打包体积。Element Plus 可以通过按需引入减少首屏加载时间,课程列表页的封面图使用懒加载。如果打包后单 chunk 文件很大,在 Vite 配置里加manualChunks,把 vue、element-plus 拆分出来,利用浏览器缓存。

10. 智能课程学习系统常见问题排查

问题现象可能原因排查方式解决方案
后端启动报invalid source release: 17JDK 版本不是 17java -version查看版本安装 JDK17 并重新设置 JAVA_HOME
MySQL 连接失败Public Key Retrieval is not allowed连接 8.0 时驱动参数问题检查 application.yml在 JDBC URL 加allowPublicKeyRetrieval=true&useSSL=false
Navicat 连接 MySQL 报 1045用户名或密码错误检查账号权限修改密码或创建远程授权账号
前端请求后端跨域代理未生效或 CORS 未配置打开浏览器 Network 看请求路径开发环境配置 Vite proxy,生产环境走 Nginx 代理
学习进度接口一直返回 401Token 未携带或过期查看请求头是否有 Authorization检查 axios 请求拦截器逻辑
页面刷新 404Nginx 没有配置 try_files查看 Nginx 日志增加/index.html回退
打包后接口地址不对前端 baseURL 是开发代理地址检查构建产物中的请求地址生产环境统一使用相对路径/api
启动后页面能开但登录失败初始化密码没有加密查看数据库密码字段使用 BCrypt 重新生成密码
定时任务不执行主启动类忘了加 @EnableScheduling查看日志有无调度输出启动类增加@EnableScheduling
统计接口越跑越慢study_record表缺少索引执行 EXPLAIN 看执行计划给 user_id、course_id、study_date 加复合索引

遇到问题先看日志,再定位代码,不要直接改数据库。SpringBoot3 的日志默认输出在控制台,生产环境可以配置logging.file.name写入文件,出现问题时翻日志的定位效率远高于反复猜测。

11. 最佳实践与使用建议

11.1 工程配置沉淀

数据库连接账号密码、JWT 密钥、文件存储路径都建议放到 profile 配置文件里,例如application-dev.yml用本地数据库,application-prod.yml用线上数据库。密码不要提交到 Git,生产密钥通过环境变量注入是最稳妥的方式。

11.2 从最小闭环开始迭代

第一次开发时不要一次做完所有模块。先把注册登录跑通,再做课程后台管理的增删改查,再做学习记录上报接口,最后做统计和推荐。前三个环节每完成一个都验证接口和页面联调,比最后统一调试省时间得多。

11.3 批量导入与接口安全

题库批量导入可以通过 Excel 或 CSV 文件上传,后端用 EasyExcel 解析后写入临时表,校验通过后统一插入正式表。凡是提供批量接口,一定需要做权限控制和文件大小限制,避免普通学员调用管理接口。批量导入时每次操作都打印日志,记录操作人、文件路径、导入条数和失败原因。

11.4 合规使用

课程系统里涉及用户生成内容时,后台必须有下架渠道。如果课程包含特定讲师出镜或有版权风险的资料,要用书面授权形式确认完整性。学员列表接口不要返回明文手机号等敏感信息,普通查询只输出昵称、学习时长等非敏感字段,这些都属于上线前必须处理的部分。

12. 总结与下一步

智能课程学习系统这个项目技术栈不偏门,SpringBoot3 + Vue3 + MySQL 是目前 Java 全栈岗位中覆盖面很广的组合。它最值得上手的地方在于“业务闭环”很完整:登录有 Spring Security 支持,课程数据有 MyBatis-Plus 的 CRUD 支撑,学习进度上报能让你思考重复提交和并发问题,学情统计则锻炼 SQL 聚合和定时任务能力。这几个点每讲清楚一个,都是给简历项目增加可信度。

想跑通这个项目,最优先验证的三个点:管理端能不能上传并上架课程;学员端能不能浏览课程并完成章节学习进度上报;统计接口能不能根据一段时间的记录生成正确学习报告。前两者保证系统基本可用,第三个决定“智能”能不能成立。最容易踩的坑是 SpringBoot3 与旧版 Security 配置差异过大导致登录认证一直失败,其次是 MySQL 连接驱动与时区参数不匹配,导致启动后所有数据库操作都抛异常。

下一步可以扩展的方向很多:接入 Redis 做课程热度榜和验证码缓存,接入消息队列做学习日志异步处理,推荐模块从标签规则升级成学习记录协同过滤算法,部署链路从 jar 手跑升级成 Docker Compose 一键编排。把一个业务闭环扎实做完,再往工程化方向横向扩展,这种路径对技术成长和面试展示都很有价值。系统跑通之后建议把项目源码整理好,README 里补上系统截图、接口文档、部署教程和演示账号,这才是 Java 全栈项目该有的完整交付状态。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/5 17:50:51

spotDL 音乐下载环境搭建:两个依赖与三种装法

spotDL 音乐下载环境搭建&#xff1a;两个依赖与三种装法 【免费下载链接】spotify-downloader Download your Spotify playlists and songs along with album art and metadata (from YouTube if a match is found). 项目地址: https://gitcode.com/GitHub_Trending/sp/spot…

作者头像 李华
网站建设 2026/9/5 17:47:16

ExplorerPatcher 终极指南:快速找回 Windows 10 任务栏和开始菜单

ExplorerPatcher 终极指南&#xff1a;快速找回 Windows 10 任务栏和开始菜单 【免费下载链接】ExplorerPatcher This project aims to enhance the working environment on Windows 项目地址: https://gitcode.com/GitHub_Trending/ex/ExplorerPatcher 还在为 Windows …

作者头像 李华
网站建设 2026/9/5 17:45:44

Echarts模板工程化:从炫酷Demo到生产级可视化组件

简介&#xff1a;本资源是一套面向数据分析、前端开发与课程设计场景的ECharts大数据可视化实战模板集&#xff0c;适用于高校学生课程设计、毕业设计、教师教学演示及企业数据看板快速搭建需求。压缩包内含100套风格多样、交互丰富的可视化大屏模板&#xff0c;覆盖疫情监控、…

作者头像 李华