ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

SpringBoot+Vue考研资讯系统:前后端分离开发与部署实战解析

2026/9/15 21:09:29 拓冰建站 浏览量
SpringBoot+Vue考研资讯系统:前后端分离开发与部署实战解析 简介基于Spring Boot和Vue的考研资讯系统面向计算机相关专业正在准备毕业设计的学生、需要课程设计或期末大作业的Java学习者以及希望掌握前后端分离实战项目的入门开发者帮助其快速获得一套可运行的完整项目。RAR压缩包约21.09MB共737个文件其中包含197个Java后端源码、137个Vue前端页面、63个JavaScript脚本以及SQL数据库脚本、Maven配置、开发文档、部署视频和代码讲解视频等前后端分层明确便于按模块检索学习。已有65人学习下载。包内附可直接运行的完整工程配合数据库脚本、环境配置说明和操作录屏可快速跑通项目并理解Spring Boot与Vue的交互流程开发文档和代码讲解视频还能辅助读者查看数据库表设计、接口调用与页面渲染细节排查部署问题或在此基础上进行功能扩展适合直接用于毕设或课程设计交付。1. 考研资讯系统在拆什么SpringBoot 与 Vue 的一条完整链路拿到这套基于 SpringBoot Vue 的考研资讯系统时我以为又是一个标准的后台管理 CRUD。真正拆开看才发现它把资讯发布、分类检索、视频课程观看、用户收藏这些场景串成了一条完整的前后端分离链路后端用 SpringBoot MyBatis 操作 MySQL 5.7前端用 Vue 渲染页面包内除了源码和 SQL 脚本还附带部署视频、代码讲解视频和一组 bat 脚本。对正在做毕业设计、课程设计或期末大作业的 Java 学习者来说它的价值不只是能跑而是一份可以对照着把环境配置复现出来的完整骨架。下面按后端接口、前端渲染、数据库脚本、部署排错四条线逐层拆开。2. SpringBoot 后端资讯接口从控制器到 MyBatis 查询落地2.1 先用项目结构确认 SpringBoot 分层用 IDEA 或 Eclipse 导入项目后先别急着点运行。后端代码在 src/main/java 下按 controller、service、mapper、entity 分包这是 SpringBoot 项目最常见的分层方式也是课程答辩时最常被问的三层架构。配置集中在 src/main/resources/application.yml数据库连接、端口、MyBatis 的 mapper 扫描路径都在这一个文件里。根目录下的 .classpath 是 Eclipse 导入时生成的工程文件mvnw.cmd 是 Maven Wrapper 脚本本机没有装 Maven 也能用它拉取依赖后执行构建只是首次运行下载较慢。我建议学生在跑项目之前先做一件事打开 application.yml检查 spring.datasource.url 里的数据库名、用户名、密码是否与本机 MySQL 一致这一步能省掉后面一半以上的报错。项目同时带有 app.25ad1ce4.css 和 main.js.bak前者是前端打包后的样式产物文件名里的 hash 是 webpack 构建时自动生成的后者是 main.js 的备份文件说明前端代码在 build 之后输出到了后端 static 目录下统一提供访问。2.2 资讯列表接口Controller、Service、Mapper 三层如何配合资讯系统的核心操作是按分类查列表和查详情对应后端接口通常是 GET /api/article/list 和 GET /api/article/detail。Controller 层只做参数接收与结果包装业务判断下沉到 ServiceMyBatis 的 Mapper 负责真正拼接 SQL。下面这段是列表接口的典型写法对照项目源码可以快速定位。RestController RequestMapping(/api/article) public class ArticleController { Resource private ArticleService articleService; GetMapping(/list) public Result list(RequestParam(defaultValue 1) Integer pageNum, RequestParam(defaultValue 10) Integer pageSize, RequestParam(required false) Integer categoryId, RequestParam(required false) String keyword) { // 分页参数交给 ServiceMyBatis 层面做 LIMIT 拼接 PageResultArticleVO page articleService.queryPage(pageNum, pageSize, categoryId, keyword); return Result.success(page); } }这里 RequestParam 的四个参数中pageNum 和 pageSize 给了默认值防止前端漏传导致 SQL 异常categoryId 和 keyword 用 required false 表示可选对应首页的按分类筛选和搜索框。Result 是统一返回结构一般包含 code、msg、data 三个字段前后端联调时只看 code 和 data 即可错误信息统一走 msg。Service 层负责计算分页偏移量并调用 Mapper常见做法如下public PageResultArticleVO queryPage(Integer pageNum, Integer pageSize, Integer categoryId, String keyword) { int offset (pageNum - 1) * pageSize; ListArticleVO list articleMapper.selectPage(offset, pageSize, categoryId, keyword); Long total articleMapper.countPage(categoryId, keyword); return PageResult.of(list, total, pageNum, pageSize); }offset 的计算是分页最容易被问到的细节pageNum 从 1 开始偏移量等于 (pageNum - 1) * pageSize。pageSize 为 10 时第二页的 offset 是 10正好跳过第一页的 10 条。total 单独用 count 查询是为了让前端分页组件能算出总页数。2.3 MyBatis 的动态 SQL 里条件查询怎么写不踩坑Mapper 接口与 XML 文件通过命名空间绑定资讯列表的 SQL 在 ArticleMapper.xml 中。查询资讯需要关联分类表查出 categoryName同时支持多个可选条件所以动态 SQL 是核心select idselectPage resultTypecom.example.vo.ArticleVO SELECT a.id, a.title, a.category_id, c.name AS category_name, a.create_time, a.view_count FROM article a LEFT JOIN category c ON a.category_id c.id where if testcategoryId ! null AND a.category_id #{categoryId} /if if testkeyword ! null and keyword ! AND (a.title LIKE CONCAT(%, #{keyword}, %) OR a.summary LIKE CONCAT(%, #{keyword}, %)) /if /where ORDER BY a.is_top DESC, a.create_time DESC LIMIT #{offset}, #{pageSize} /select这里有三个点答辩时值得展开。第一LEFT JOIN 而不是 INNER JOIN可以避免某条资讯的分类被删除后详情页直接查不到数据。第二LIKE 查询用 CONCAT 拼接 %而不是在 Java 侧拼好再传入因为 #{keyword} 会走预编译能防止 SQL 注入。第三ORDER BY 先按 is_top 置顶标记降序再按 create_time 降序这是考研资讯首页置顶优先的实现来源。MySQL 5.7 对 LIMIT offset, pageSize 的写法直接支持配合 count 查询即可完成分页闭环。接口参数与返回约定可用下表快速核对前端对接时按这个约定走能避免联调阶段反复改字段名。接口参数返回结构GET /api/article/listpageNum、pageSize、categoryId、keywordPageResult含 total、listGET /api/article/detailidArticleVO含 content 富文本GET /api/category/list无ListCategoryVOPOST /api/favorite/addarticleIdResultcode 200 表示成功3. Vue 前端渲染链路从路由参数到资讯页面与 m3u8 视频观看3.1 vue-router 怎么把分类参数带给资讯列表页前端工程中 vue-router 把 URL 映射到组件。从分类页跳转到资讯列表时常见做法是把 categoryId 作为查询参数传递目标页面通过 $route.query 读取。查询参数会保留在 URL 上刷新不丢失适合列表页这类可以分享链接的场景$route.params 适合页面内部状态刷新后会丢失两者在使用场景上要区分清楚。// 分类页跳转到资讯列表 this.$router.push({ path: /article/list, query: { categoryId: this.currentCategory.id } }) // 资讯列表页读取参数并发起请求 const categoryId this.$route.query.categoryId this.loadList({ categoryId })前端拿到 categoryId 后调用后端 /api/article/list请求动作放在 Vue 组件的 created 钩子里。如果同一个列表页内需要切换分类则要把请求逻辑放进 watch 监听路由变化否则点击其他分类时页面不会重新加载数据。这是 vue-router 使用里非常典型的一个坑。3.2 Axios 封装与接口跨域配置页面里的所有请求一般通过统一的 request.js 发出axios 实例设置 baseURL 和超时时间。开发环境下前端运行在 8080后端端口以 application.yml 为准跨域通过 vue.config.js 的 devServer.proxy 解决而不是在后端写 CrossOrigin因为代理方案对上线部署同样友好。// src/api/request.js 简化版 import axios from axios const request axios.create({ baseURL: /api, timeout: 10000 }) request.interceptors.response.use( res { if (res.data.code 200) { return res.data.data } return Promise.reject(new Error(res.data.msg)) }, err Promise.reject(err) ) export default request// vue.config.js 开发环境代理 module.exports { devServer: { proxy: { /api: { target: http://localhost:8081, changeOrigin: true } } } }baseURL 里的 /api 与代理 target 中的端口必须同后端 server.port 一致这是环境配置里最常对不上的点。拦截器里统一拆包后页面代码不用每次判断 res.code直接拿到业务数据代码会干净很多。如果后端接口报 404优先确认代理 target 端口而不是怀疑接口路径写错。3.3 资讯详情页的视频课程与 m3u8 切片播放考研资讯系统通常不止有文字资讯还会挂载考研公开课、专业课导学视频。整段 mp4 加载慢且拖动卡顿所以资讯类系统里视频课程多采用 ts 分片加 m3u8 索引的方式播放。Vue 页面播放 m3u8 的常见做法是 video.js 配合 hls 支持template video idcourseVideo classvideo-js vjs-big-play-centered controls/video /templateimport videojs from video.js import video.js/dist/video-js.css // 引入 hls 支持后直接指定 m3u8 地址 const player videojs(courseVideo, { sources: [{ src: this.course.videoUrl, // 形如 https://cdn.xxx.com/course/01/index.m3u8 type: application/x-mpegURL }] }) this.player player播放 m3u8 的关键点是 src 的跨域支持。视频资源和前端不在同一域名时视频服务器必须返回 CORS 响应头否则分片请求会被浏览器拦截表现是视频一直黑屏但控制台没有明显报错。另外组件销毁时要调用 player.dispose() 释放实例否则路由切换多次后会出现多个播放器叠加声音和画面不同步的问题就与它直接相关。3.4 打包后的 CSS 与布局异常排查项目里出现的 app.25ad1ce4.css 是 Vue 工程 build 之后的产物文件名带 hash 表示内容经过了打包压缩属于正常现象。如果打包部署后页面白屏或布局完全错乱优先检查 vue.config.js 中的 publicPath。默认配置下资源路径是绝对路径 /部署到子目录时浏览器找不到 JS 和 CSS表现为白屏能找到 JS 但样式全丢则表现为布局异常。处理方式是改成相对路径module.exports { publicPath: ./, outputDir: dist }改完配置后重新执行 build打开 dist/index.html 检查 script 和 link 标签src 与 href 应该变成相对路径的 ./js/...。把前端 build 产物复制到 SpringBoot 的 static 目录统一部署时这个坑几乎必踩一次样式丢失首先怀疑它。4. MySQL 5.7 的表结构设计与 Navicat 导入4.1 建表脚本先看这三张核心表数据库脚本是项目能跑起来的前提。考研资讯系统的数据模型不复杂但分类与资讯、用户与收藏之间的关系必须理清。以分类表、资讯表、收藏表为例MySQL 5.7 建表语句如下字符集统一用 utf8mb4否则资讯标题里出现 emoji 或生僻字时会报 Incorrect string value 错误。CREATE DATABASE IF NOT EXISTS ky_info DEFAULT CHARACTER SET utf8mb4; USE ky_info; CREATE TABLE category ( id INT NOT NULL AUTO_INCREMENT COMMENT 分类ID, name VARCHAR(50) NOT NULL COMMENT 分类名称, sort_order INT DEFAULT 0 COMMENT 排序权重, PRIMARY KEY (id) ) ENGINEInnoDB AUTO_INCREMENT1 COMMENT资讯分类表; CREATE TABLE article ( id INT NOT NULL AUTO_INCREMENT COMMENT 资讯ID, category_id INT NOT NULL COMMENT 所属分类ID, title VARCHAR(200) NOT NULL COMMENT 标题, summary VARCHAR(500) DEFAULT NULL COMMENT 摘要, content LONGTEXT COMMENT 正文内容, cover_url VARCHAR(500) DEFAULT NULL COMMENT 封面图地址, is_top TINYINT DEFAULT 0 COMMENT 是否置顶 0否 1是, view_count INT DEFAULT 0 COMMENT 浏览量, create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT 发布时间, PRIMARY KEY (id), KEY idx_category_time (category_id, create_time) ) ENGINEInnoDB COMMENT考研资讯表; CREATE TABLE favorite ( id INT NOT NULL AUTO_INCREMENT, user_id INT NOT NULL COMMENT 用户ID, article_id INT NOT NULL COMMENT 资讯ID, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY idx_user (user_id) ) ENGINEInnoDB COMMENT用户收藏表;article 表在 category_id 和 create_time 上建了联合索引因为列表页最常见的查询路径是先按分类过滤再按时间排序这个索引同时覆盖 where 和 order by。favorite 表只对 user_id 建普通索引用于快速查询某用户收藏了哪些资讯。is_top 用 TINYINT 而不是 BOOLEAN因为 MySQL 中 BOOLEAN 只是 TINYINT(1) 的别名用 TINYINT 语义更清晰也方便以后扩展置顶等级。导入完成后可以顺手插入几条测试数据用来验证列表接口是否通INSERT INTO category (name, sort_order) VALUES (院校信息, 1), (专业课, 2), (复试调剂, 3); INSERT INTO article (category_id, title, summary, content, is_top) VALUES (1, 2026 考研院校报录比汇总, 近三年报录比数据整理, p内容略/p, 1);4.2 Navicat11 导入脚本的操作流项目包内附带的数据库脚本通常是一个 .sql 文件。用 Navicat11 导入时先新建连接确认 MySQL 5.7 服务已启动然后右键新建数据库名称建议与后端 application.yml 中的 jdbc url 保持一致最后双击打开该数据库右键运行 SQL 文件选择脚本运行后按 F5 刷新能看到 category、article 等表就算成功。导入过程中有两个高频报错。脚本头部已经包含 CREATE DATABASE 时不要再手动新建同名库否则会有库名冲突或重复建表报错外键约束导致的导入失败会报 cannot add foreign key constraint此时检查父表是否存在、字段类型是否一致特别是 INT 与 BIGINT 混用也触发该错误。4.3 版本匹配要注意的三个边界这套项目的运行环境是 JDK 1.8、MySQL 5.7、Maven 3.3围绕这三个版本搭建最省事擅自升级会带来连带问题。JDK 1.8 跑 Spring Boot 2.x 没问题但换成 Spring Boot 3.x 必须升级到 JDK 17否则启动阶段直接报 UnsupportedClassVersionError。MySQL 5.7 升到 8.0 后驱动类要从 com.mysql.jdbc.Driver 换成 com.mysql.cj.jdbc.Driverurl 上还要追加 serverTimezoneAsia/Shanghai否则日期相关查询报时区错误。Maven 3.3 对大部分 Spring Boot 2.x 依赖的拉取没有障碍依赖下载慢时优先检查镜像配置而不是升级版本。环境项项目要求升级后的连带影响JDK1.8Spring Boot 3.x 需要 JDK 17MySQL5.78.0 需换驱动类和时区参数Maven3.33.6 构建无大影响旧版本可能不支持部分插件Navicat11新版功能更多脚本导入方式一致5. 部署脚本 1-install.bat 到 run.bat 的排错要点5.1 bat 脚本与 application.yml 的关键配置项目根目录下的 1-install.bat、2-run.bat、3-build.bat 是一套按顺序执行的部署流程install.bat、run.bat、build.bat 是同一流程的精简命名。1-install.bat 先执行 Maven 打包并跳过测试再进入前端目录执行 npm install2-run.bat 启动后端 jar 和前端服务3-build.bat 负责生产构建。执行前先确认 JAVA_HOME 指向 JDK 1.8否则 bat 脚本里的 java 命令会找不到或版本不对。:: 1-install.bat 核心命令 mvn clean install -DskipTests cd frontend npm install提示install 阶段卡在依赖下载时优先检查 Maven 镜像配置常见做法是换成阿里云镜像仓库。后端启动前核对 application.yml 三项配置server.port 决定后端端口spring.datasource.url 里的数据库名必须和 Navicat 中建好的库一致spring.datasource.password 要填本机 MySQL 的 root 密码。这三处不一致会导致启动失败或接口 500。5.2 常见报错对照与启动脚本的可复用改动启动失败先看控制台前几行高频问题集中在端口占用和数据库连接。端口占用报 Port already in use处理方式是改端口或释放占用进程数据库连不上报 Communications link failure先检查 MySQL 5.7 服务状态和密码中是否含特殊字符。m3u8 视频黑屏则检查视频服务器 CORS 头这类问题对照下面的表现能快速定位现象定位方向常规处理后端启动报端口占用8080 被占用改 application.yml 端口或释放进程接口能访问但列表为空库名或表不存在确认导入脚本的库名与 url 一致前端白屏且无请求publicPath 绝对路径改为 ./ 后重新 buildm3u8 视频一直黑屏视频服务器跨域检查 CORS 响应头项目自带 mvnw.cmd本机 Maven 3.3 异常时可以改用 mvnw.cmd spring-boot:run。最后给一个可复用的启动改动把 2-run.bat 里的启动命令改成带内存参数并输出日志的形式。start ky-info java -Xms256m -Xmx512m -jar target/ky-info.jar app.log 21这样再次启动失败时直接看 app.log不用守着控制台窗口。按顺序执行 1-install.bat、2-run.bat 后浏览器访问首页接口能看到 JSON 返回整条链路就确认跑通了。本文还有配套的精品资源点击获取