Spring Boot+Vue在线教育系统实战:从零构建前后端分离项目

发布时间:2026/9/2 5:11:28
Spring Boot+Vue在线教育系统实战:从零构建前后端分离项目 最近在辅导学生毕业设计和课程设计时发现很多同学对如何构建一个完整的、前后端分离的在线教育系统感到无从下手。网上资料要么过于零散要么只讲理论没有完整源码导致项目难以落地。本文将分享一套基于 Spring Boot Vue 的在线教育系统完整实战方案从需求分析、技术选型、环境搭建到核心功能实现提供完整的源码和详细的步骤讲解。无论你是需要完成毕设、课程设计还是想通过一个实战项目深入学习 Spring Boot 和 Vue这篇文章都能为你提供一条清晰的路径。1. 项目背景与核心概念在线教育系统是当前非常热门且实用的应用场景它模拟了真实的教育平台如慕课网、腾讯课堂等涵盖了用户管理、课程管理、视频播放、在线测试、订单支付等核心功能。对于学习者而言通过开发这样一个系统可以系统地串联起前后端分离开发的全栈技术栈。核心概念解析Spring Boot一个用于简化 Spring 应用初始搭建和开发过程的框架。它通过“约定大于配置”的理念内嵌了 Tomcat 等 Web 服务器让开发者可以快速创建独立运行、生产级别的基于 Spring 的应用程序。在本项目中它承担后端 API 服务的角色负责业务逻辑处理、数据持久化和接口提供。Vue.js一套用于构建用户界面的渐进式 JavaScript 框架。它采用组件化开发模式数据驱动视图使得前端开发更加高效和易于维护。在本项目中它负责构建用户交互界面通过 Axios 等工具与后端 Spring Boot API 进行通信。前后端分离这是现代 Web 开发的主流架构。后端Spring Boot专注于提供 RESTful API处理数据和业务逻辑前端Vue专注于页面渲染和用户交互。两者通过 HTTP 协议进行 JSON 格式的数据交换。这种架构使得前后端可以独立开发、测试和部署提高了开发效率和系统的可维护性。在线教育系统核心模块通常包括用户端和管理端。用户端功能有注册登录、浏览课程、购买课程、观看视频、参与讨论、个人中心等。管理端功能有用户管理、课程分类管理、课程内容管理上传视频、文档、订单管理、数据统计等。掌握这个项目的开发不仅能让你完成一个高质量的毕设或课设更能让你深入理解企业级应用的分层架构、数据库设计、接口设计、权限控制以及前后端协同开发的完整流程。2. 环境准备与版本说明在开始编码之前请确保你的开发环境已就绪。以下是本文示例所使用的主要环境及版本请务必根据你的实际情况进行调整不同版本间可能存在细微差异。后端环境 (Spring Boot):操作系统Windows 10/11, macOS, 或 Linux (如 Ubuntu)JDK版本 8 或 11 (推荐 OpenJDK 11)。Spring Boot 2.x 对 JDK 8 兼容性最好Spring Boot 3.x 则需要 JDK 17。构建工具Apache Maven 3.6 或 Gradle。本文使用 Maven 进行依赖管理。IDEIntelliJ IDEA (社区版或旗舰版) 或 Eclipse with STS 插件。IDEA 对 Spring Boot 支持更友好。数据库MySQL 5.7 或 8.0。我们将使用 MySQL 作为持久化存储。其他工具Postman 或 Apifox (用于 API 测试) Git (版本控制)。前端环境 (Vue):Node.js版本 14.x 或 16.x (推荐 LTS 版本)。这是运行 Vue 和 npm 的基础。包管理器npm 或 yarn。本文使用 npm。Vue CLI版本 4.x 或 5.x。用于快速搭建 Vue 项目脚手架。IDEVisual Studio Code (VSCode) 或 WebStorm。VSCode 轻量且插件丰富。版本说明与建议为了最大兼容性和稳定性本教程的代码示例将基于以下较为主流的版本组合进行讲解。你可以在创建项目时选择相近版本。Spring Boot:2.7.x(一个非常稳定且资料丰富的版本系列)Vue:2.x(考虑到生态成熟度和学习资料仍推荐 Vue 2) 或3.x(如果你想使用最新特性)MySQL Connector:8.0.xMyBatis-Plus:3.5.x(极大简化数据库操作)重要提示在开始一个新项目时建议通过 Spring Initializr 和 Vue CLI 来生成项目骨架它们会自动处理大部分依赖版本兼容性问题。如果遇到依赖冲突请仔细查阅官方文档。3. 系统设计与技术栈拆解一个结构清晰的设计是项目成功的基础。我们先从整体架构和数据库设计入手。3.1 系统架构图本项目采用典型的前后端分离架构。用户浏览器 (前端 Vue App) | | (HTTP/HTTPS, JSON) v Nginx (反向代理/静态资源服务器) | | (代理请求) v 后端 Spring Boot 应用 (运行在Tomcat) | | (JDBC) v MySQL 数据库前端使用 Vue CLI 创建的单页面应用(SPA)通过 Axios 调用后端 REST API。后端Spring Boot 应用采用 MVC 分层模式Controller, Service, Mapper。数据库MySQL用于存储所有业务数据。部署开发阶段前端通过npm run serve运行开发服务器后端通过 IDEA 直接运行。生产环境可使用 Nginx 部署前端静态文件并代理 API 请求到后端 Jar 包。3.2 核心数据库表设计以下是几个核心业务表的设计用于理解数据模型。用户表 (sys_user):CREATE TABLE sys_user ( id bigint(20) NOT NULL AUTO_INCREMENT COMMENT 主键ID, username varchar(50) NOT NULL COMMENT 用户名, password varchar(100) NOT NULL COMMENT 密码加密后, nick_name varchar(50) DEFAULT NULL COMMENT 昵称, avatar varchar(255) DEFAULT NULL COMMENT 头像URL, email varchar(100) DEFAULT NULL COMMENT 邮箱, phone varchar(20) DEFAULT NULL COMMENT 手机号, user_type tinyint(1) DEFAULT 0 COMMENT 用户类型0-学生1-教师2-管理员, status tinyint(1) DEFAULT 1 COMMENT 状态0-禁用1-正常, create_time datetime DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间, update_time datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 更新时间, PRIMARY KEY (id), UNIQUE KEY uk_username (username) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT用户表;课程表 (edu_course):CREATE TABLE edu_course ( id bigint(20) NOT NULL AUTO_INCREMENT COMMENT 课程ID, teacher_id bigint(20) NOT NULL COMMENT 讲师ID, category_id bigint(20) DEFAULT NULL COMMENT 课程分类ID, title varchar(100) NOT NULL COMMENT 课程标题, cover varchar(255) DEFAULT NULL COMMENT 课程封面图片URL, description text COMMENT 课程简介, price decimal(10,2) DEFAULT 0.00 COMMENT 课程价格, lesson_num int(11) DEFAULT 0 COMMENT 课时数, view_count bigint(20) DEFAULT 0 COMMENT 浏览数量, status varchar(20) DEFAULT Draft COMMENT 课程状态Draft-未发布Normal-已发布, create_time datetime DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间, update_time datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 更新时间, PRIMARY KEY (id), KEY idx_teacher_id (teacher_id), KEY idx_category_id (category_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT课程表;章节表 (edu_chapter)和小节/视频表 (edu_video)会与课程表关联形成树形结构。此外还需要订单表 (edu_order)、购物车表 (edu_cart)、评论表 (edu_comment)等。这里不一一列举。3.3 后端技术栈详解Spring Boot Starter Web:提供 Web MVC 功能内置 Tomcat。Spring Boot Starter Data JDBC / MyBatis-Plus:用于数据库访问。MyBatis-Plus 在 MyBatis 基础上做了增强提供了通用的 CRUD 方法无需编写简单 SQL。Spring Boot Starter Validation:用于接口参数校验如NotBlank,Email。Spring Boot Starter Security (可选):用于实现系统的认证和授权。对于毕设也可以使用简单的 Token (如 JWT) 方案。Druid:阿里巴巴开源的数据库连接池提供强大的监控和扩展功能。Lombok:通过注解自动生成 Getter/Setter、构造方法等减少样板代码。JWT (JSON Web Token):用于生成和验证用户登录令牌实现无状态认证。3.4 前端技术栈详解Vue Core:Vue.js 核心库。Vue Router:官方路由管理器用于构建单页面应用。Vuex (Vue 2) / Pinia (Vue 3):状态管理库用于集中管理跨组件共享的状态如用户登录信息。Axios:基于 Promise 的 HTTP 客户端用于向后端发送请求。Element UI (Vue 2) / Element Plus (Vue 3):基于 Vue 的桌面端组件库能快速搭建美观的界面。也可选择 Ant Design Vue、Vant 等。其他工具库:vue-video-player(用于播放视频)echarts(用于数据图表展示) 等。4. 后端 Spring Boot 项目实战接下来我们开始搭建后端项目。我们将创建一个名为edu-online-backend的 Spring Boot 项目。4.1 创建项目与基础配置使用 Spring Initializr (在线或 IDEA 内置) 创建项目。Project:MavenLanguage:JavaSpring Boot:2.7.xGroup:com.exampleArtifact:edu-online-backendPackaging:JarJava:8 或 11依赖选择Spring WebLombokMyBatis FrameworkMySQL Driver创建完成后在pom.xml中手动添加一些常用依赖!-- MyBatis-Plus 替代 MyBatis -- dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version3.5.3.1/version /dependency !-- Druid 连接池 -- dependency groupIdcom.alibaba/groupId artifactIddruid-spring-boot-starter/artifactId version1.2.16/version /dependency !-- JWT 支持 -- dependency groupIdio.jsonwebtoken/groupId artifactIdjjwt/artifactId version0.9.1/version /dependency !-- 参数校验 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-validation/artifactId /dependency4.2 数据库连接与 MyBatis-Plus 配置在src/main/resources/application.yml中配置数据库和 MyBatis-Plusserver: port: 8080 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/edu_online?useUnicodetruecharacterEncodingUTF-8serverTimezoneAsia/Shanghai username: root password: your_password type: com.alibaba.druid.pool.DruidDataSource druid: initial-size: 5 min-idle: 5 max-active: 20 test-on-borrow: true mybatis-plus: configuration: # 下划线转驼峰 map-underscore-to-camel-case: true # 日志实现 log-impl: org.apache.ibatis.logging.stdout.StdOutImpl global-config: db-config: # 全局逻辑删除字段名 logic-delete-field: deleted # 逻辑已删除值 logic-delete-value: 1 # 逻辑未删除值 logic-not-delete-value: 0 # mapper.xml 文件位置 mapper-locations: classpath*:/mapper/**/*.xml4.3 核心代码实现用户登录与 JWT1. 创建实体类 (Entity)对应sys_user表。// 文件路径src/main/java/com/example/eduonline/entity/User.java package com.example.eduonline.entity; import com.baomidou.mybatisplus.annotation.*; import lombok.Data; import java.time.LocalDateTime; Data TableName(sys_user) public class User { TableId(type IdType.AUTO) private Long id; private String username; private String password; private String nickName; private String avatar; private String email; private String phone; private Integer userType; // 0-学生1-教师2-管理员 private Integer status; // 0-禁用1-正常 TableField(fill FieldFill.INSERT) private LocalDateTime createTime; TableField(fill FieldFill.INSERT_UPDATE) private LocalDateTime updateTime; }2. 创建 Mapper 接口继承 MyBatis-Plus 的BaseMapper获得基础 CRUD 方法。// 文件路径src/main/java/com/example/eduonline/mapper/UserMapper.java package com.example.eduonline.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.example.eduonline.entity.User; import org.apache.ibatis.annotations.Mapper; Mapper public interface UserMapper extends BaseMapperUser { }3. 创建 Service 层// 文件路径src/main/java/com/example/eduonline/service/UserService.java package com.example.eduonline.service; import com.baomidou.mybatisplus.extension.service.IService; import com.example.eduonline.entity.User; public interface UserService extends IServiceUser { String login(String username, String password); User getByUsername(String username); }// 文件路径src/main/java/com/example/eduonline/service/impl/UserServiceImpl.java package com.example.eduonline.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.example.eduonline.entity.User; import com.example.eduonline.mapper.UserMapper; import com.example.eduonline.service.UserService; import com.example.eduonline.utils.JwtUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.util.DigestUtils; Service public class UserServiceImpl extends ServiceImplUserMapper, User implements UserService { Autowired private JwtUtil jwtUtil; Override public String login(String username, String password) { // 1. 根据用户名查询用户 LambdaQueryWrapperUser wrapper new LambdaQueryWrapper(); wrapper.eq(User::getUsername, username); User user this.getOne(wrapper); if (user null) { throw new RuntimeException(用户名或密码错误); } // 2. 校验状态 if (user.getStatus() 0) { throw new RuntimeException(用户已被禁用); } // 3. 校验密码 (示例使用MD5加密生产环境请用BCrypt) String encryptedPassword DigestUtils.md5DigestAsHex(password.getBytes()); if (!encryptedPassword.equals(user.getPassword())) { throw new RuntimeException(用户名或密码错误); } // 4. 生成JWT令牌 return jwtUtil.generateToken(user.getId(), user.getUsername(), user.getUserType()); } Override public User getByUsername(String username) { LambdaQueryWrapperUser wrapper new LambdaQueryWrapper(); wrapper.eq(User::getUsername, username); return this.getOne(wrapper); } }4. 创建 JWT 工具类// 文件路径src/main/java/com/example/eduonline/utils/JwtUtil.java package com.example.eduonline.utils; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import java.util.Date; import java.util.HashMap; import java.util.Map; Component public class JwtUtil { Value(${jwt.secret:eduOnlineSecretKey}) // 从配置读取默认值 private String secret; Value(${jwt.expiration:86400000}) // 默认24小时 private Long expiration; public String generateToken(Long userId, String username, Integer userType) { MapString, Object claims new HashMap(); claims.put(userId, userId); claims.put(username, username); claims.put(userType, userType); return Jwts.builder() .setClaims(claims) .setSubject(username) .setIssuedAt(new Date()) .setExpiration(new Date(System.currentTimeMillis() expiration)) .signWith(SignatureAlgorithm.HS512, secret) .compact(); } public Claims parseToken(String token) { return Jwts.parser() .setSigningKey(secret) .parseClaimsJws(token) .getBody(); } public boolean isTokenExpired(String token) { return parseToken(token).getExpiration().before(new Date()); } public Long getUserIdFromToken(String token) { return parseToken(token).get(userId, Long.class); } // ... 其他解析方法 }5. 创建 Controller 层// 文件路径src/main/java/com/example/eduonline/controller/UserController.java package com.example.eduonline.controller; import com.example.eduonline.common.Result; import com.example.eduonline.entity.User; import com.example.eduonline.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import javax.validation.constraints.NotBlank; RestController RequestMapping(/api/user) public class UserController { Autowired private UserService userService; PostMapping(/login) public Result login(RequestParam NotBlank String username, RequestParam NotBlank String password) { try { String token userService.login(username, password); return Result.success(登录成功, token); } catch (RuntimeException e) { return Result.error(e.getMessage()); } } GetMapping(/info) public Result getUserInfo(RequestHeader(Authorization) String token) { // 实际应从token解析用户ID然后查询数据库 // 这里简化处理直接返回一个模拟对象 User user new User(); user.setUsername(student1); user.setNickName(张三); user.setUserType(0); return Result.success(user); } }6. 统一返回结果封装// 文件路径src/main/java/com/example/eduonline/common/Result.java package com.example.eduonline.common; import lombok.Data; Data public class ResultT { private Integer code; private String msg; private T data; public static T ResultT success(T data) { ResultT result new Result(); result.setCode(200); result.setMsg(操作成功); result.setData(data); return result; } public static T ResultT success(String msg, T data) { ResultT result new Result(); result.setCode(200); result.setMsg(msg); result.setData(data); return result; } public static T ResultT error(String msg) { ResultT result new Result(); result.setCode(500); result.setMsg(msg); return result; } // 可以定义更多状态码如 400(参数错误)401(未授权)403(禁止访问)等 }4.4 运行与验证在 MySQL 中创建数据库edu_online并运行前面提供的sys_user建表 SQL。插入一条测试用户数据密码使用 MD5 加密例如密码123456加密后为e10adc3949ba59abbe56e057f20f883e。INSERT INTO sys_user (username, password, nick_name, user_type, status) VALUES (student1, e10adc3949ba59abbe56e057f20f883e, 测试学生, 0, 1);启动 Spring Boot 应用 (EduOnlineBackendApplication)。使用 Postman 测试登录接口URL:POST http://localhost:8080/api/user/loginBody:x-www-form-urlencodedusername:student1password:123456预期返回{code:200,msg:登录成功,data:eyJhbGciOiJIUzUxMiJ9...JWT令牌}5. 前端 Vue 项目实战后端 API 准备就绪后我们开始搭建前端项目。我们将创建一个名为edu-online-frontend的 Vue 2 项目。5.1 创建项目与安装依赖使用 Vue CLI 创建项目。vue create edu-online-frontend选择Manually select features然后勾选Babel,Router,Vuex,CSS Pre-processors(如 Sass)Linter / Formatter按需选择。选择 Vue 2 版本。创建完成后进入项目目录并安装 Element UI 和 Axios。cd edu-online-frontend npm install element-ui axios # 如果使用 Vue 3则安装 element-plus # npm install element-plus5.2 项目结构与基础配置在src/main.js中引入 Element UI 和全局样式。// 文件路径src/main.js import Vue from vue import App from ./App.vue import router from ./router import store from ./store import ElementUI from element-ui import element-ui/lib/theme-chalk/index.css import axios from axios Vue.config.productionTip false Vue.use(ElementUI) // 配置axios基准URL和请求拦截器用于添加JWT Token axios.defaults.baseURL http://localhost:8080 // 后端地址 axios.interceptors.request.use(config { const token localStorage.getItem(token) if (token) { config.headers.Authorization Bearer ${token} } return config }, error { return Promise.reject(error) }) // 响应拦截器处理通用错误 axios.interceptors.response.use(response { return response.data }, error { // 处理HTTP错误状态码如401跳转登录 if (error.response error.response.status 401) { router.push(/login) } return Promise.reject(error) }) Vue.prototype.$axios axios new Vue({ router, store, render: h h(App) }).$mount(#app)5.3 核心页面实现登录页面创建登录组件src/views/Login.vue。template div classlogin-container el-card classlogin-card h2 styletext-align: center; margin-bottom: 30px;在线教育系统/h2 el-form :modelloginForm :rulesloginRules refloginFormRef label-width80px el-form-item label用户名 propusername el-input v-modelloginForm.username placeholder请输入用户名/el-input /el-form-item el-form-item label密码 proppassword el-input v-modelloginForm.password typepassword placeholder请输入密码 keyup.enter.nativehandleLogin/el-input /el-form-item el-form-item el-button typeprimary stylewidth:100%; :loadingloading clickhandleLogin登录/el-button /el-form-item /el-form div styletext-align: center; margin-top: 20px; color: #999; span测试账号: student1 / 123456/span /div /el-card /div /template script export default { name: Login, data() { return { loginForm: { username: , password: }, loginRules: { username: [{ required: true, message: 请输入用户名, trigger: blur }], password: [{ required: true, message: 请输入密码, trigger: blur }] }, loading: false } }, methods: { handleLogin() { this.$refs.loginFormRef.validate(valid { if (valid) { this.loading true this.$axios.post(/api/user/login, null, { params: { username: this.loginForm.username, password: this.loginForm.password } }).then(res { if (res.code 200) { this.$message.success(res.msg) // 存储token到localStorage和Vuex localStorage.setItem(token, res.data) this.$store.commit(setToken, res.data) // 跳转到首页 this.$router.push(/) } else { this.$message.error(res.msg) } }).catch(err { this.$message.error(登录失败 (err.msg || err.message)) }).finally(() { this.loading false }) } }) } } } /script style scoped .login-container { display: flex; justify-content: center; align-items: center; height: 100vh; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); } .login-card { width: 400px; padding: 30px; } /style5.4 路由与状态管理配置修改src/router/index.js添加登录路由和主页路由。// 文件路径src/router/index.js import Vue from vue import VueRouter from vue-router import Login from ../views/Login.vue import Home from ../views/Home.vue Vue.use(VueRouter) const routes [ { path: /login, name: Login, component: Login }, { path: /, name: Home, component: Home, meta: { requiresAuth: true } // 需要认证 } // ... 其他路由 ] const router new VueRouter({ mode: history, base: process.env.BASE_URL, routes }) // 路由守卫检查登录状态 router.beforeEach((to, from, next) { const token localStorage.getItem(token) if (to.matched.some(record record.meta.requiresAuth)) { if (!token) { next(/login) } else { next() } } else { next() } }) export default router修改src/store/index.js管理用户状态和 Token。// 文件路径src/store/index.js import Vue from vue import Vuex from vuex Vue.use(Vuex) export default new Vuex.Store({ state: { token: localStorage.getItem(token) || , userInfo: null }, mutations: { setToken(state, token) { state.token token localStorage.setItem(token, token) }, clearToken(state) { state.token localStorage.removeItem(token) }, setUserInfo(state, info) { state.userInfo info } }, actions: { // 可以在这里定义异步action如获取用户信息 async getUserInfo({ commit }) { const res await this.$axios.get(/api/user/info) if (res.code 200) { commit(setUserInfo, res.data) } } }, getters: { isLoggedIn: state !!state.token } })5.5 运行前端项目在项目根目录下运行npm run serve访问http://localhost:8081(默认端口)即可看到登录页面。输入测试账号student1和密码123456点击登录成功后应跳转到首页Home.vue需要你自行创建。6. 核心功能扩展与联调至此我们完成了前后端最基本的登录功能联调。一个完整的在线教育系统还需要更多模块。6.1 课程列表与详情页后端创建CourseController,CourseService,CourseMapper提供课程分页查询、详情查询接口。前端创建CourseList.vue和CourseDetail.vue组件使用el-table,el-pagination展示列表使用el-card展示详情。6.2 视频播放功能这是在线教育的核心。可以使用vue-video-player结合video.js。安装依赖npm install vue-video-player video.js后端课程视频文件可以存储在服务器本地或对象存储如阿里云OSS、腾讯云COS。需要提供视频文件的访问URL或经过签名的临时URL。前端在课程详情页集成播放器组件。template div video-player :optionsplayerOptions/video-player /div /template script import { videoPlayer } from vue-video-player import video.js/dist/video-js.css export default { components: { videoPlayer }, data() { return { playerOptions: { autoplay: false, controls: true, sources: [{ src: http://your-server.com/path/to/video.mp4, // 从后端接口获取的视频地址 type: video/mp4 }] } } } } /script注意对于m3u8格式的视频流常用于直播或点播video.js需要配合videojs-contrib-hls插件。6.3 购物车与订单数据库设计edu_cart(购物车) 和edu_order(订单) 表。后端实现添加商品到购物车、查看购物车、生成订单、订单支付可模拟等接口。前端实现对应的页面和交互逻辑。6.4 权限控制页面级权限通过 Vue Router 的meta属性和路由守卫实现如上文示例。按钮级权限可以自定义一个指令v-permission根据用户角色控制按钮显示。接口级权限在后端可以通过 Spring Security 或自定义拦截器根据 JWT Token 解析出的用户角色判断是否有权访问某个 API。7. 常见问题与排查思路在开发过程中你可能会遇到以下典型问题问题现象常见原因解决思路前端npm run serve报错Node.js 版本不兼容、依赖安装失败、端口被占用1. 检查 Node.js 版本 (node -v)。2. 删除node_modules和package-lock.json重新npm install。3. 更改vue.config.js中的devServer.port。后端启动失败报DataSource相关错误数据库连接失败、驱动版本不匹配、时区设置问题1. 检查application.yml中的数据库 URL、用户名、密码。2. 确认 MySQL 服务已启动。3. 在数据库 URL 中添加serverTimezoneAsia/Shanghai。4. 检查 MySQL 驱动版本与数据库版本是否匹配。前端调用后端 API 返回 404 (Not Found)后端接口路径错误、前端代理配置错误、跨域问题1. 用 Postman 直接测试后端接口确认接口可用。2. 检查前端axios.defaults.baseURL是否正确。3. 开发环境下可在vue.config.js中配置代理解决跨域jsbrdevServer: {br proxy: {br /api: {br target: http://localhost:8080,br changeOrigin: truebr }br }br}br前端登录成功但后续请求返回 401 (Unauthorized)Token 未正确传递、Token 过期、后端解析 Token 失败1. 检查前端请求拦截器是否将 Token 正确放入Authorization头。2. 检查后端 JWT 工具类中的secret是否一致Token 是否过期。3. 在后端添加一个拦截器或过滤器来统一验证 Token。MyBatis-Plus 插入或查询时字段映射错误实体类字段名与数据库列名不对应驼峰 vs 下划线1. 在application.yml中确认map-underscore-to-camel-case: true。2. 使用TableField注解指定数据库列名。视频无法播放视频地址错误、视频格式浏览器不支持、服务器未正确返回视频流1. 在浏览器地址栏直接输入视频 URL看是否能下载或播放。2. 确保服务器正确配置了视频文件的 MIME 类型。3. 对于大文件考虑使用分片传输或流媒体服务器。8. 项目优化与最佳实践完成基础功能后可以从以下几个方面优化你的项目使其更接近生产级别。1. 后端优化统一异常处理使用ControllerAdvice和ExceptionHandler全局捕获异常返回统一的错误格式而不是在 Controller 中到处try-catch。接口文档集成 Swagger 或 Knife4j自动生成 API 文档便于前后端联调。数据校验在接收参数的 DTO 类上使用Valid注解和校验注解如NotBlank,Email并在全局异常处理器中处理校验失败异常。密码安全切勿使用 MD5存储密码。应使用BCryptPasswordEncoder进行加盐哈希。日志记录使用 SLF4J Logback 记录详细的运行日志便于排查问题。单元测试为 Service 层和 Controller 层编写单元测试保证代码质量。2. 前端优化API 模块化将所有的 API 请求封装到单独的api目录下的文件中如user.js,course.js便于维护。组件化开发将可复用的 UI 部分如课程卡片、分页组件抽离成独立组件。路由懒加载在router/index.js中使用() import(/views/xxx.vue)语法实现路由懒加载提升首屏加载速度。环境变量使用.env.development和.env.production文件管理不同环境下的 API 地址等配置。打包优化使用npm run build打包时可以配置vue.config.js进行代码压缩、分包等优化。3. 部署上线后端使用mvn clean package打成可执行的 JAR 包在服务器上通过java -jar your-app.jar运行。建议使用nohup或配置为系统服务如 systemd。前端使用npm run build生成静态文件在dist目录将其部署到 Nginx 或 Apache 等 Web 服务器上。数据库做好定期备份。对于生产环境考虑主从复制、读写分离等方案。安全配置 HTTPS、设置防火墙规则、定期更新依赖库以修复安全漏洞。4. 扩展方向增加搜索功能集成 Elasticsearch实现课程标题、描述的全文检索。引入消息队列使用 RabbitMQ 或 Kafka处理异步任务如发送购买成功邮件、记录学习日志。微服务化将用户服务、课程服务、订单服务拆分为独立的微服务使用 Spring Cloud 进行治理。容器化部署使用 Docker 将前后端应用容器化通过 Docker Compose 或 Kubernetes 进行编排管理。通过以上步骤你已经拥有了一个功能相对完整、代码结构清晰的在线教育系统雏形。这个项目涵盖了从需求分析、技术选型、环境搭建、数据库设计、前后端编码到部署优化的全流程非常适合作为毕业设计或课程设计的选题。你可以在此基础上继续深化某个模块如实现更复杂的权限系统、集成第三方支付、开发移动端小程序等使其成为你简历中的一个亮点项目。