资讯动态

SpringBoot+Vue智能学习平台管理平台:全栈开发与部署指南

发布时间:2026/10/8 19:51:17 来源:尧图企业网站定制
这类SpringBootVue智能学习平台管理平台的项目我可以说是看得太多了。每年毕设季和课设季后台私信里问得最多的就是这类标题的项目GitHub上相关的开源仓库也是成百上千。老实说这类项目之所以能成为毕设、课设的常青树不是没有道理的——技术栈主流、业务场景清晰、功能模块足够丰富既能撑起论文的篇幅又能让答辩老师觉得这学生是真的做了东西的。今天我就把这类项目的完整技术拆解、核心模块设计、数据库表结构、前后端对接的关键代码、本地跑通的完整流程以及那些只有在实际开发中才会踩到的坑一次性说清楚。不管你是准备拿这个项目做毕设还是纯粹想通过一个完整项目把 SpringBoot 和 Vue 的全栈开发流程串一遍这篇文章都值得你存下来慢慢看。1. 项目定位与核心需求拆解先说清楚这个项目到底是个什么东西。所谓的智能学习平台管理平台本质上就是一个在线教育系统的后台管理端负责管理前台学习网站的所有数据和业务。它和学习平台前台是配套的但管理端的功能侧重点完全不同——前台是给学生看课程、看视频、做练习的管理端是给运营人员、老师、管理员用的要处理的是内容发布、用户管理、数据统计、权限控制这些事。你可以把它理解成一个学校教务系统内容管理系统的结合体只不过业务场景放在了在线学习这个领域。1.1 智能体现在哪里很多同学看到智能学习平台这个前缀就以为要上人工智能、推荐算法、大数据分析这些高大上的东西。实际上对于毕设和课设来说智能主要体现在三个落地上这三个点也是论文里可以重点描写的创新点。第一个是数据统计可视化。平台要记录用户的学习行为比如登录次数、学习时长、课程完成率、章节学习进度然后通过图表把这些数据展示出来让管理员能直观地看到平台的运营状况。这一块通常用 ECharts 就能实现不需要引入额外的大数据组件。第二个是学习路径的个性化推荐简化版。很多毕设会做一个根据用户学习记录推荐相关课程的功能实现方案通常是记录用户看过的课程分类统计用户对各类课程的偏好权重然后根据偏好权重推荐同分类下用户没看过的、评分较高的课程。第三个是自动化的课程上下架管理。传统的教育平台需要人工审核课程内容是否合规、是否过期智能学习平台则可以设定规则——比如课程有效期到期自动下架、课程章节学习人数达到阈值自动标记为热门课程、异常登录自动锁定账号等这些都是可以用定时任务或者触发器来实现的。如果这三个点能做到论文的创新点部分就已经有内容可写了完全不虚。1.2 目标用户与使用场景这个项目适合三类人你可以对号入座。第一类是正在准备毕业设计的本科生计算机相关专业已经学过 Java 基础和数据库原理但对 SpringBoot 和 Vue 的整合还比较陌生需要一套完整的、能跑通的代码作为参照。第二类是准备课程设计的大二、大三学生时间紧任务重可能只有两到四周的周期需要一个短平快的项目来完成任务同时保证代码质量足够答辩。第三类是自学全栈开发的入门者想通过一个业务逻辑不算复杂、但技术覆盖全面的项目把前端 Vue 和后端 SpringBoot 的交互流程彻底搞清楚。对于这三类人我的建议是一样的拿到源码之后不要急着跑起来先花一两天时间把目录结构、数据库表关系、接口调用链路看明白然后再动手改需求、换皮肤、加功能。直接跑起来再改代码的大概率会把项目越改越乱最后自己都不知道哪里出了问题。2. 技术选型与架构设计这类项目的技术栈组合非常固定后端 SpringBoot、前端 Vue、数据库 MySQL整套下来就是目前国内 Java 全栈开发最主流、最好找工作的一套技术栈。很多同学问我为什么不用 SpringCloud 微服务、为什么不用前后端不分离的 Thymeleaf、为什么不用 MongoDB原因其实很现实。2.1 核心选型的理由SpringBoot 的选择几乎不需要犹豫。它内置了 Tomcat自动配置了一大堆常用组件开发者只需要关心业务代码不需要像 SSM 时代那样写大量 XML 配置。对于毕设来说SpringBoot 最大的好处是开箱即用哪怕你 Spring 原理没吃透也能快速把项目跑起来而且 SpringBoot 的面试题也最容易准备。Vue 的选择同样合理。Vue2 的生态在国内是最成熟的Element UI 组件库写后台管理界面快到飞起而且网上 Vue2 的学习资料、答疑帖是最多的遇到问题随便一搜就有答案。至于 Vue3 和 TypeScript如果你对前端不熟我不建议在毕设里硬上——Vue3 的生态虽然已经很完善但对新手来说组合式 API 和 TS 类型约束会显著拉长开发周期而这个项目的前端工作量本来就不小。MySQL 的选择是没得选。绝大多数的毕设和课设指定用 MySQL而且 MySQL 的安装、可视化工具Navicat、DataGrip、学习资料都是最丰富的遇到问题好排查。除这三个核心组件之外还会用到以下这些框架和工具我把版本推荐和选型理由整理成了一张表组件推荐版本选型理由JDK1.8 或 11企业生产环境大量使用 JDK8稳定且兼容性好SpringBoot2.x如 2.7.x避免直接用 3.x3.x 要求 JDK17 且部分教程不兼容MyBatis-Plus3.5.x单表 CRUD 不用写 SQL内置分页插件比 MyBatis 快很多JWTjjwt 0.9.x 或 0.11.x无状态认证前后端分离项目的标准做法Lombok1.18.x消除 getter/setter 样板代码Vue2.6.x 或 2.7.x生态成熟Element UI 完美配合Element UI2.15.x最常用的 Vue2 管理端 UI 库Axios0.21.x 以上前端 HTTP 请求库统一封装ECharts5.x数据可视化图表库2.2 前后端分离的整体架构这个项目的架构是典型的前后端分离结构前端 Vue 项目通过 Axios 向后端 SpringBoot 项目发 HTTP 请求后端提供 RESTful API数据存到 MySQL 中。前端和后端独立部署、独立开发通过 JSON 格式的数据进行交互。这里要特别提醒一下前后端分离意味着你的项目在开发时会有两个端口。Vue 开发服务器默认跑在 8080SpringBoot 默认跑在 8080或 8081 等端口两者端口必须不同否则起冲突。前端通过代理proxy或后端配置跨域CORS来实现两个端口之间的请求转发。我见过太多同学在这个环节卡半天项目起不来最后发现是端口冲突或者跨域没配好。这一块的具体配置方法我会在后面实操环节详细说这里先建立一个整体概念。整个项目的标准目录结构大致是这样的├── backendSpringBoot 后端 │ ├── src/main/java │ │ └── com/example/studyplatform │ │ ├── config # 配置类跨域、拦截器、MyBatis-Plus分页 │ │ ├── controller # 控制器层接收前端请求 │ │ ├── entity # 实体类对应数据库表 │ │ ├── mapper # MyBatis-Plus 接口层 │ │ ├── service # 业务逻辑层 │ │ └── utils # 工具类JWT工具、统一返回结果等 │ └── src/main/resources │ ├── application.yml # 核心配置文件 │ └── mapper # XML文件复杂SQL写在XML里 ├── frontendVue 前端 │ ├── src │ │ ├── api # 所有API请求封装 │ │ ├── assets # 静态资源 │ │ ├── components # 公共组件 │ │ ├── router # 路由配置 │ │ ├── store # Vuex 状态管理 │ │ ├── views # 页面组件 │ │ ├── App.vue │ │ └── main.js │ ├── package.json │ └── vue.config.js # Vue 配置文件含代理 └── sql └── study_platform.sql # 数据库初始化脚本这个目录结构是符合主流开发规范的拿到任何同类项目你都可以用这个结构来快速定位代码位置而不是在一堆文件里瞎翻。3. 后端核心功能设计与数据库实现后面这一部分会是全文的重头戏。我先把后端核心模块的设计思路拆开讲再把数据库表结构、API 设计、关键代码逐段展开。你会发现所谓的管理平台功能再怎么多、界面再怎么花哨核心的底座就是几张表和围绕这几张表的一堆增删改查接口。3.1 核心功能模块清单一个完整的学习平台管理端通常包含以下这些模块我直接按模块列出它们要做什么登录与权限模块管理员登录、JWT 签发、密码加密、角色权限控制。管理端一般分为超管、课程管理员、普通运营人员等角色不同角色能看到的菜单和能操作的按钮不一样。用户管理模块管理前台注册的学生用户包括查看用户列表、条件搜索用户名、手机号、状态、禁用/启用用户、重置密码、查看用户详情含学习记录概览。课程管理模块课程分类管理增删改查、课程信息管理封面、标题、简介、价格、上下架状态、课程章节管理添加/编辑/删除章节每个章节可以关联视频地址或资料文件。学习记录模块记录每个用户对每个章节课时的学习进度包括已学时长、完成状态、最后学习时间。后台可以按课程维度或用户维度查看学习完成率。考试测验模块创建试卷、管理题目单选、多选、判断、设定考试时间窗口、查看考试成绩列表。公告管理模块发布系统公告支持富文本编辑前台公告列表同步展示。数据统计模块首页仪表盘展示核心指标——平台总用户数、总课程数、今日新增用户、总学习次数并用折线图、饼图展示近30天用户活跃趋势课程分类占比用户学习时长排行等。这七个模块做下来论文的需求分析部分可以有图有表地写三四页功能测试部分可以写十几条测试用例工作量是完全够的。3.2 数据库设计表结构为核心数据库设计是整个项目的灵魂。很多同学拿到源码第一件事就是跑起来看效果但如果你要改需求、做答辩数据库是必须吃透的。一个学习平台管理端的核心表主要就是下面这几张表名说明关键字段sys_user后台管理员表id, username, password, real_name, role_id, status, create_timestudent前台学生用户表id, username, password, nickname, phone, status, avatar, create_timecourse_category课程分类表id, name, sort, create_timecourse课程表id, category_id, title, cover, summary, price, status, teacher, create_timecourse_chapter课程章节表id, course_id, title, video_url, duration, sortuser_study_record学习记录表id, student_id, chapter_id, course_id, study_duration, is_complete, update_timeexam考试/试卷表id, title, duration, start_time, end_time, total_score, statusexam_question题目表id, exam_id, question_type, content, option_a, option_b, option_c, option_d, answer, scoreexam_record学生考试记录表id, exam_id, student_id, score, submit_timenotice公告表id, title, content, create_time, statussys_role角色表id, role_name, role_code, description这里说一个关键点课程表设计时上下架状态这个字段非常重要。status 字段用一个小整数表示0 表示草稿/未上架1 表示已上架2 表示已下架。不要用字符串上架下架这种格式数据库里凡是状态类字段一律用整型枚举这是规范问题也是答辩时老师可能会问的点。课程和分类是 N:1 关系一个课程只能属于一个分类一个分类下可以有多个课程章节和课程是 N:1 关系学习记录和章节、课程、学生分别是 N:1 关系。这些关系在数据库里通过外键逻辑关联不推荐物理外键逻辑关联即可性能更好在代码里通过注解关联查询。3.3 SpringBoot 后端的分层设计与核心代码后端的包结构我上面已经画过了这里讲一下各层的职责和关键代码模式。Controller 层只做参数接收和结果返回不写业务逻辑。一个标准的接口长这样RestController RequestMapping(/api/admin/course) public class CourseController { Autowired private CourseService courseService; GetMapping(/page) public Result getCoursePage(RequestParam Integer pageNum, RequestParam Integer pageSize, RequestParam(required false) String title, RequestParam(required false) Integer categoryId) { PageCourse page courseService.getCoursePage(pageNum, pageSize, title, categoryId); return Result.success(page); } PostMapping public Result addCourse(RequestBody Course course) { courseService.addCourse(course); return Result.success(); } PutMapping(/status) public Result updateStatus(RequestParam Integer id, RequestParam Integer status) { courseService.updateStatus(id, status); return Result.success(); } DeleteMapping(/{id}) public Result deleteCourse(PathVariable Integer id) { courseService.deleteCourse(id); return Result.success(); } }注意看几个细节统一返回结果 Result 是这个项目里非常重要的一层封装。Result 的格式通常是三个字段code、message、datacode 为 200 表示成功其余为失败。这样前端拦截器可以根据 code 统一判断请求成功与否不用每个接口单独判断。分页操作使用的是 MyBatis-Plus 的 Page 对象前端传入页码和每页条数后端返回分页数据和总条数。Service 层是业务逻辑的核心所在。比如删除课程这个操作就不仅仅是删掉 course 表的一条记录你还要把该课程下的所有章节、所有用户的学习记录一并处理掉否则数据库里会留下大量孤儿数据。Service public class CourseServiceImpl extends ServiceImplCourseMapper, Course implements CourseService { Override public void deleteCourse(Integer id) { // 删除课程基本信息 this.removeById(id); // 删除该课程下的所有章节 chapterService.remove(new LambdaQueryWrapperCourseChapter() .eq(CourseChapter::getCourseId, id)); // 删除该课程下的所有学习记录 studyRecordService.remove(new LambdaQueryWrapperUserStudyRecord() .eq(UserStudyRecord::getCourseId, id)); } }这段代码体现了事务性的思维要么全部成功要么全部失败。实际项目里会在 deleteCourse 方法上加上 Transactional 注解保证多个删除操作在同一事务中执行防止中途出错导致数据不一致。这个点是很多初学者容易忽略的但却是答辩时老师最喜欢追问的点之一。3.4 JWT 登录认证与权限拦截登录认证这一块很多同学用 Session 做虽然能跑但前后端分离项目里Session 需要处理跨域 Cookie 问题非常麻烦。更主流的做法是 JWTJSON Web Token。JWT 的工作流程是这样的用户登录成功后后端把用户 ID、用户名、角色等信息加密生成一个 Token 字符串返回给前端。前端把它存在 localStorage 里之后每次请求都在请求头里带上这个 Token。后端通过拦截器解析 Token判断用户是否登录、是否有权限访问该接口。核心的拦截器代码如下Component public class JwtInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 前端在请求头中携带 token String token request.getHeader(Authorization); if (StringUtils.isBlank(token)) { throw new RuntimeException(未登录请先登录); } try { // 解析 token如果过期或非法会抛异常 Claims claims JwtUtil.parseToken(token); request.setAttribute(userId, claims.get(userId)); request.setAttribute(roleId, claims.get(roleId)); } catch (Exception e) { throw new RuntimeException(登录已过期请重新登录); } return true; } }然后通过 WebMvcConfigurer 将拦截器注册进去并配置哪些路径需要拦截、哪些路径放行比如登录接口、图片静态资源路径放行。关于 JWT我需要强调几个常见坑。第一个JWT 的密钥secret不要写死在代码里放到 application.yml 配置文件中通过 Value 注解读取这是规范做法。第二个JWT 默认不加密payload 里不要放密码等敏感信息只能放用户 ID 和角色这类非敏感字段。第三个JWT 的过期时间不要设置得太长一般建议 2-12 小时过期后前端需要跳转登录页让用户重新登录。这三个点每一个都可以在答辩时展开讲上几分钟。密码加密方面不要用明文存数据库使用 Spring Security 自带的 BCryptPasswordEncoder它每次生成的密文都不同安全性远高于 MD5 加盐而且用法非常简单// 加密 String encodedPwd new BCryptPasswordEncoder().encode(123456); // 校验 boolean matches new BCryptPasswordEncoder().matches(123456, encodedPwd);3.5 文件上传与富文本处理管理端涉及课程封面上传这个功能实现起来也不复杂。SpringBoot 接收 multipart 文件存储到本地磁盘目录然后向前端返回可访问的 URL。这里需要注意文件不能直接存到项目内部的 target 目录否则重新部署时文件会丢失。合理的做法是配置一个独立的磁盘路径并通过一个静态资源映射把这个目录映射为 URL 路径对外访问。在 application.yml 中这样配置file: upload-path: D:/study-platform/upload/ spring: mvc: static-path-pattern: /** resources: static-locations: file:${file.upload-path},classpath:/static/上传接口的核心逻辑PostMapping(/upload) public Result uploadFile(RequestParam(file) MultipartFile file) { // 判断文件是否为空 if (file.isEmpty()) { return Result.error(文件不能为空); } // 获取原始文件名生成新的文件名防止重名覆盖 String originalFilename file.getOriginalFilename(); String suffix originalFilename.substring(originalFilename.lastIndexOf(.)); String newFileName UUID.randomUUID().toString().replace(-, ) suffix; // 保存文件到指定目录 File dir new File(fileUploadPath); if (!dir.exists()) { dir.mkdirs(); } file.transferTo(new File(fileUploadPath newFileName)); // 返回可访问的完整 URL String fileUrl /upload/ newFileName; return Result.success(fileUrl); }这个接口里有两个常见的坑。第一个是文件名重名问题必须用 UUID 重新生成文件名否则两个用户上传同名的图片会互相覆盖。第二个是目录必须先创建否则 transferTo 会报 FileNotFoundException。这些细节都属于看起来简单、踩起来要命的典型。富文本编辑器一般用 wangEditor 这个国内开源项目前端集成非常简单后端只需要增加一个图片上传的接口供编辑器调用即可。公告表的 content 字段用 text 类型存 HTML 字符串前端展示时用 v-html 渲染。这一套方案在毕设中已经足够用。4. 前端 Vue 核心实现与 API 对接前端部分的工作量一点也不比后端小但它有非常成熟的套路可循。管理端前端的核心任务就是用 Element UI 组件搭建页面、用 Axios 跟后端交互、用 Vue Router 做页面跳转和权限控制、用 Vuex 存全局的用户信息和菜单状态。4.1 Vue 项目的初始化与配置前端项目基于 Vue CLI 创建。如果电脑上还没有 CLI 工具先装一下npm install -g vue/cli vue create smart-study-admin选择 Vue2 预设创建完成之后再安装项目运行所需的核心依赖npm install element-ui axios vue-router vuex echarts这一块有几个环境坑需要先避开。坑一npm 下载慢到怀疑人生解决办法是切换到国内镜像源npm config set registry https://registry.npmmirror.com。坑二Vue CLI 创建项目时检测到 Node.js 版本过高会报错常见于 Node 17 以上版本解决办法是在 package.json 中把 dev 脚本改一下set NODE_OPTIONS--openssl-legacy-provider vue-cli-service serve。坑三安装完依赖之后 node_modules 目录非常庞大拷贝项目的时候不要带这个目录到新环境直接 npm install 即可否则拷来拷去容易把 node_modules 弄坏。这三个坑我可不是在网上看来的是自己在毕设季帮人排错时反复遇到的。前端的请求封装是管理端项目的基石不建议直接用 axios 裸调。我在项目中通常先在 src/utils/request.js 下统一封装加入 baseURL、请求头携带 Token、响应拦截统一处理错误码代码如下import axios from axios import { Message } from element-ui import router from ../router const request axios.create({ baseURL: /api, timeout: 10000 }) // 请求拦截器自动携带token request.interceptors.request.use(config { const token localStorage.getItem(token) if (token) { config.headers[Authorization] token } return config }) // 响应拦截器统一处理返回结果 request.interceptors.response.use(response { const res response.data if (res.code 200) { return res } else { Message.error(res.message || 请求失败) return Promise.reject(new Error(res.message)) } }, error { if (error.response error.response.status 401) { Message.error(登录已过期请重新登录) localStorage.removeItem(token) router.push(/login) } else { Message.error(网络异常请稍后重试) } return Promise.reject(error) }) export default request这里把 baseURL 统一设为 /api后端接口路径统一以 /api 开头。为什么这么设计因为 Vue 开发服务器可以将所有以 /api 开头的请求通过代理转发到后端服务这样前后端端口不一致的问题就彻底解决了。开发时和后端真正联调的代理配置如下// vue.config.js module.exports { devServer: { port: 8080, proxy: { /api: { target: http://localhost:8081, changeOrigin: true } } } }这样配置之后前端开发地址是 http://localhost:8080它会自动把/api/login这样的请求转发到 http://localhost:8081/api/login。后端 SpringBoot 项目把 server.port 设为 8081两边各跑各的互不干扰。4.2 登录页与路由权限控制登录页是一个管理端的脸面也是前后端交互的第一个功能。前端流程是用户输入用户名密码调用 /api/admin/login 接口成功后把 Token 存入 localStorage再调用 /api/admin/info 获取用户信息角色、头像、姓名存入 Vuex最后根据角色跳转到对应的首页。登录按钮的逻辑大致是这样的handleLogin() { this.$refs.loginForm.validate(async valid { if (!valid) return const res await login(this.loginForm) localStorage.setItem(token, res.data.token) const userInfo await getAdminInfo() this.$store.commit(SET_USER_INFO, userInfo.data) this.$router.push(/dashboard) }) }路由权限控制是前端另一个核心点没登录的用户不能访问管理端页面非管理员不能访问超管专属页面。实现方案是用 Vue Router 的全局前置守卫router.beforeEach((to, from, next) { const token localStorage.getItem(token) if (to.path /login) { next() } else { if (!token) { next(/login) } else { // 可选按角色过滤路由 next() } } })有些毕设还要求区分角色则可以在 Vuex 中存角色信息在路由 meta 中标记需要的角色守卫里判断一下即可。这一块虽然代码量不大但属于前端面试高频题答辩的时候几乎必问。4.3 管理端布局与 CRUD 页面范式管理端布局基本是左侧菜单右侧内容的经典结构Element UI 的 el-container 组件直接搞定。菜单按照角色动态渲染数据可以从后端接口动态获取也可以直接在前端写死毕设建议前端写死减少一个接口复杂度但如果你要增加菜单管理的功能模块那就必须用后端动态菜单了这里我推荐学有余力的同学用动态菜单论文和答辩素材都更丰富。一个标准的 CRUD 页面以用户管理为例通常包含四个部分搜索区、表格区、分页区、操作按钮区。核心模板结构如下template div classuser-manage !-- 搜索区 -- el-form :inlinetrue el-form-item label用户名 el-input v-modelqueryParams.username placeholder请输入用户名 clearable / /el-form-item el-form-item label状态 el-select v-modelqueryParams.status el-option label全部 value / el-option label正常 :value1 / el-option label禁用 :value0 / /el-select /el-form-item el-form-item el-button typeprimary clickgetList()查询/el-button el-button clickresetQuery()重置/el-button /el-form-item /el-form !-- 表格区 -- el-table :datatableData border stripe el-table-column propid labelID width60 / el-table-column propusername label用户名 / el-table-column propnickname label昵称 / el-table-column propphone label手机号 / el-table-column label状态 template slot-scopescope el-tag :typescope.row.status 1 ? success : danger {{ scope.row.status 1 ? 正常 : 禁用 }} /el-tag /template /el-table-column el-table-column label操作 template slot-scopescope el-button typeprimary sizesmall clickhandleEdit(scope.row)编辑/el-button el-button typedanger sizesmall clickhandleDelete(scope.row)删除/el-button /template /el-table-column /el-table !-- 分页区 -- el-pagination current-changegetList :current-pagequeryParams.pageNum :page-sizequeryParams.pageSize layouttotal, prev, pager, next :totaltotal /el-pagination /div /template这套模板可以快速复制到课程管理、章节管理、公告管理等任何 CRUD 页面中只需要改 table-column 的字段名和搜索条件。写完后端的同学如果第一次接触前端用这个套路能在两三天内把整个管理端页面搭出来。4.4 ECharts 数据可视化实现首页仪表盘的数据可视化是整个项目最出彩、也最容易被学生做砸的部分。说它容易做砸是因为很多同学的图表数据是写死的答辩老师一动数据库里的数据图表纹丝不动一眼就露馅。正确的做法是图表的所有数据从后端接口动态获取。先定义接口GetMapping(/api/admin/dashboard/stats) public Result getDashboardStats() { MapString, Object stats new HashMap(); // 总用户数 stats.put(userCount, studentService.count()); // 总课程数 stats.put(courseCount, courseService.count()); // 今日新增用户数 stats.put(todayNewUser, studentService.getTodayNewUserCount()); // 近30天用户活跃趋势返回日期和对应的活跃数两个数组 stats.put(activeTrend, studyRecordService.getActiveTrend()); // 分类课程占比返回分类名和课程数两个数组 stats.put(categoryRatio, courseService.getCategoryRatio()); return Result.success(stats); }前端拿到数据后再通过 setOption 填充到 ECharts 图表中。这样无论数据库里的数据怎么变化图表都会跟着实时更新。5. 本地部署与全流程跑通指南代码写得再漂亮跑不起来就是零分。这一节我用最啰嗦的方式把从零到一定能把项目跑通的完整流程走一遍。别嫌我话多严格按照这个顺序来大概率能省掉你三个小时的折腾时间。5.1 环境准备与安装检查项目要跑起来你的电脑上需要准备这些东西我按重要性排序JDK 8 或 11并配置好 JAVA_HOME 环境变量。安装完后命令行输入 java -version 能输出版本号才算安装成功。MySQL 5.7 或 8.0。推荐 MySQL 5.7兼容性最好网上教程最多。安装时记住 root 密码。Navicat 或 DataGrip 等数据库可视化工具用于手动执行 SQL 脚本。Node.js 14 或 16 版本。装完后命令行输入 node -v 和 npm -v 都能输出版本号。Maven 3.6.x 以上用于后端项目的依赖管理和启动。装完后命令行输入 mvn -v 能输出版本号。IDEA 或 Eclipse推荐 IDEA社区版免费就够用。其中比较容易出问题的是 JDK 和 MySQL 的版本匹配。JDK8 可以完美支持 MySQL 8.0 的连接驱动但有个细节MySQL 8.0 的驱动类名是 com.mysql.cj.jdbc.Driver而 5.7 是 com.mysql.jdbc.Driver。如果后端连不上数据库先检查一下 application.yml 里的 driver-class-name、url、账号密码这三项是否和你本机环境一致。5.2 初始化数据库与后端配置用 Navicat 新建一个数据库名字随意比如 study_platform字符集选 utf8mb4排序规则选 utf8mb4_general_ci。然后把项目自带的 SQL 脚本拖进去执行。执行完之后检查一下核心表是否都建好了。如果 SQL 脚本缺失你需要根据表结构手动建表工作量不小所以拿到源码后第一件事就是确认 SQL 文件是完整的。接着修改后端 application.yml 里的数据库连接信息server: port: 8081 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/study_platform?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: root password: 123456 # 改成你自己的数据库密码url 里有个 serverTimezoneAsia/Shanghai 参数这个参数是 MySQL 8.0 连接必需的不加会报时区错误。如果你的 MySQL 是 5.7同样建议保留不碍事。后端启动方式有两种在 IDEA 中直接运行主类上的 main 方法或者在项目根目录执行mvn spring-boot:run命令。推荐第一种更方便看日志排错。确认后端启动成功的方法是浏览器访问某个放行的接口比如 http://localhost:8081/api/admin/health能返回 JSON 数据说明启动正常。5.3 前端依赖安装与启动前端项目根目录执行npm install npm run servenpm install 时间会比较长网速好的话两三分钟网速差可能十分钟往上走。如果报错优先考虑换镜像源后再删掉 node_modules 重新安装。启动成功后终端会显示 Local: http://localhost:8080浏览器打开这个地址就能看到登录页。后端端口 8081、前端端口 8080通过代理转发两边才算是联调起来。到这里如果你能看到登录页、输错密码会提示错误、输对默认管理员账号能登录进系统并展示后台页面那么恭喜你项目已经百分之百跑通了。剩下的时间就应该花在业务代码的修改和论文的撰写上而不是继续折腾环境了。5.4 前后面联调时的跨域与请求异常排查前端代理转发和后端跨域配置两者只要有其一就能跑通但很多项目源码两处都配了这时反而会产生重复问题。如果你发现请求一直失败把前后端浏览器 F12 的控制台打开仔细看报错信息。常见报错及处理方式我列成了一个排查表报错信息可能原因解决方案Access to XMLHttpRequest ... blocked by CORS policy后端跨域未配置在 SpringBoot 中配置 CorsFilter 或 CrossOrigin404 Not Found后端端口/路径与前端代理不一致检查 vue.config.js 的 target 和 request.js 的 baseURLNetwork Error后端未启动或端口错误确认浏览器访问后端接口能否返回数据401 UnauthorizedToken 缺失或过期检查 localStorage 中 token 是否在请求头传递502 Bad Gateway代理指向错误的后端口检查代理 target 是否填对Connection refused后端启动失败或端口被占用查看 IDEA 控制台日志排查启动报错这里我特别强调 404 的排查思路浏览器 F12 中的 Network 标签页能看到请求的真实 URL对比前端实际请求的 URL 和后端 RequestMapping 的路径是否一致。很多项目里的路径是 /api/admin/login代码里却是 /api/admin/login/一个斜杠的差别就是 404 和 200 的距离。6. 源码使用的常见问题与答辩避坑心得到了这一节已经默认你的项目能跑起来了。接下来你大概率会在修改代码和准备答辩的过程中遇到下面这些问题我提前帮你踩一遍。6.1 源码使用过程中的典型问题拿到源码后最常见的三个问题是改菜单文本、换 logo、改接口地址。这些看起来是小改动但处理不当能把项目搞崩。改前端页面上的文字和图片属于纯静态修改直接改即可改完页面热更新不用重启。但改接口地址一定要谨慎——如果前端调用的接口和后端 Controller 里的路径不一致页面就会报 404。最稳妥的做法是全局搜一下接口路径确保前后对照无误。改数据库中的默认管理员密码不要在数据库里直接把 password 字段改成明文。因为这个项目的密码是 BCrypt 加密的你改成共享的明文后登录时 BCryptPasswordEncoder 校验必然失败。正确做法是写一个测试类用 BCryptPasswordEncoder 生成新密码的密文再替换数据库中的对应字段。关于课程视频的接入这个问题我需要多说一句。很多同学喜欢弄一个 m3u8 格式的视频来做学习平台的课程内容因为这样可以做分片传输体验比较好。如果你要用 m3u8前端视频播放组件确实需要做额外的处理常规的 video 标签只能播 mp4 格式。建议在毕设阶段统一用 mp4 格式的视频直链简单省事。还有一个高频问题前端开发环境跑通了后端也能跑通但前后端连在一起就有问题。此时请把浏览器 F12 打开切换到 Network 标签页点击那条请求查看 Request URL 是不是正确的代理地址再点 Response 看后端返回了什么。这套排查流程十个问题能排除掉八个。6.2 数据库表字段设计的加分细节答辩时老师打开你的数据库第一眼会看你表设计得规范不规范。几个加分项你值得拥有第一个所有表必须要有 create_time 和 update_time 字段。MyBatis-Plus 可以自动填充这两个字段在实体类上加上 TableField(fill FieldFill.INSERT) 注解然后实现 MetaObjectHandler 接口即可自动填充。第二个删除操作尽量使用逻辑删除而不是物理删除。在表中加一个 deleted 字段0 未删除1 已删除配合 MyBatis-Plus 的 TableLogic 注解调用 removeById 时底层会执行 UPDATE 而不是 DELETE。这样做的好处是数据可恢复、不影响历史统计也是企业开发的标准规范。第三个金额字段要用 decimal 类型而不是 float/double浮点类型有精度丢失问题。视频时长字段建议用 int单位是秒而不是直接用字符串存12:34这种格式否则做统计计算的时候会非常痛苦。这三个细节是很多网上的源码不会特意教你的但答辩的时候稍微讲一讲老师会觉得你确实下了功夫。6.3 答辩环节的经验之谈最后聊聊答辩这可能是比写代码更让人紧张的一关。根据我带过的学生情况来看答辩翻车很少是因为代码跑不起来更多的死法是因为——不知道怎么讲清楚自己的项目、回答不了老师的深挖提问。你坐在讲台上老师大概率会问以下这些问题我提前把应对思路写出来你这个项目用了什么技术栈 标准回答要分层前端 Vue2 Element UI后端 SpringBoot 2.x MyBatis-Plus数据库 MySQL认证用的是 JWT。每说到一个技术名词最好加一句我当时选它是因为 XXX显得你不是背出来的而是经过思考选择的。你这个系统的权限是怎么控制的 这个问题我已经在 3.4 节详细讲过了你去复习一下就知道怎么回答。核心要说清楚登录后生成 JWT请求时拦截器解析 Token再根据角色 ID 判断接口访问权限。数据库表之间是怎么设计的 拿出你准备好的 ER 图先讲主表再讲关联关系重点讲课程表和章节表、学习记录表之间的外键逻辑。不要把所有表都背一遍讲核心关联即可。学习记录里的智能学习是怎么实现的 这是你的创新点环节。把学习记录、课程完成率统计、数据可视化和简单的推荐逻辑讲清楚就是在证明你的智能不是空话。事先把这些问题准备好答辩的底气会完全不同。还有一个心态上的技巧回答老师的追问时哪怕不确定也先说出自己的思路再老实地表示这一块我没有深入还需要继续学习。老师要看到的是你的思考过程不要求你是一个经验丰富的工程师但你得证明自己知道自己在做什么。我的个人实操体会这个项目我前前后后帮忙调试过不下二十个同学的代码有些话想放在最后说。很多人一拿到源码就急着跑起来看完页面效果好就觉得自己已经会了。这其实是最容易掉进去的坑。跑起来只是第一步——你真要学会的是用这个项目去理解一套完整系统的协作方式前端页面怎么通过 API 调用后端数据后端怎么通过 ORM 存取数据库数据库的表结构又是如何支撑业务逻辑的。这一整条链路吃透了你去面试 Java 开发岗时项目经验这一项就能讲得特别扎实。另外我强烈建议你在跑通原版代码之后主动改一两个功能。不需要改得很复杂哪怕只是给用户列表增加一个按注册时间排序的按钮或者给课程管理增加一个批量上下架的功能这个过程的价值远比多看十篇教程都大。因为改代码的过程就是逼你去读懂别人代码的过程而读懂代码才是吃透项目的开始。做毕设也好、自学也好目的从来不是找一个能用的答案而是搞清楚答案为什么是这个样子。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑