ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Spring Boot + Vue后台管理系统毕设包:从环境对齐到答辩加分

Spring Boot + Vue后台管理系统毕设包:从环境对齐到答辩加分 简介这是一份基于Spring Boot与Ant Design Vue Pro搭建的简易后台管理系统源码包定位为毕业设计或课程设计项目适合计算机相关专业计科、人工智能、通信工程、自动化、电子信息等学生完成毕设选题、课设作业、初期立项演示也适合具备Java与Vue基础的学习者作为前后端分离实战的完整参考。压缩包共391个文件整体约960KB以132个Vue页面组件、104个Java后端逻辑、83个JavaScript交互脚本为主另有Less样式、XML配置、SQL数据库脚本与YML环境配置可清晰对应前端页面、后端接口与数据库设计目录结构也便于按模块定位和修改。项目代码经过实际运行验证功能稳定作者标注答辩评审平均分达96分下载后可按README说明快速启动并根据自身毕设或课设需求扩展业务模块、替换应用场景。已有58人学习/下载适合在此基础上继续扩展后台管理功能或用于完善权限管理、数据统计等模块也可直接作为毕业设计答辩演示素材。1. 拿到「基于springboot、蚂蚁设计vue pro的简易后台管理系统.zip」之后先做这三件事一个命名为「基于springboot蚂蚁设计vue pro的简易后台管理系统.zip」的毕设包解压后基本是后端一份 Spring Boot 工程、前端一份 Ant Design Vue Pro 工程外加若干 SQL 脚本和说明文档。最反直觉的地方是这个包越接近“能直接运行”你越要警惕环境版本和数据库配置因为zip里跑通过一次不代表换台电脑也能跑通。这类工程通常由脚手架生成原作者本地的 JDK、Node、MySQL 版本和你并不一致所以第一次打开时你真正要做的事不是写新功能而是先让“能跑”这个目标达成。这篇笔记就是按这个顺序讲从拆包对齐环境到前后端联调再到加一个演示模块最后把最容易让答辩翻车的坑一次性排掉。2. 从 zip 走到能跑的环境Spring Boot 版本和前端脚手架先对齐2.1 先把 zip 解压并确认后端 Spring Boot 大版本毕业设计的 zip 往往嵌套了一层文件夹直接解压到桌面后先别双击 IDEA先在命令行里看结构免得 IDEA 把前端目录也当成 Maven 工程加载。unzip -q 基于springboot和vue的简易后台管理系统.zip -d 简易后台管理系统 cd 简易后台管理系统 ls -la find . -maxdepth 2 -name pom.xml -o -name package.json这段命令的作用是从压缩包释放出全部文件然后用find定位后端 Maven 配置和前端 Node 配置。正常情况下你会看到backend/、frontend/或者类似的独立目录如果看到多个pom.xml说明工程打包时把无关代码也带进来了这时以路径最浅、结构最完整的那份为准。接下来关键一步是看 Spring Boot 版本cd backend grep -A 3 spring-boot-starter-parent pom.xml如果pom.xml里没有这个 parent就搜dependencyManagement同样能看到 Spring Boot 版本号。Spring Boot 2.7 和 3.x 之间不是小事3.x 要求 JDK 17并且把javax.*换成了jakarta.*如果你本机只有 JDK 8直接跑 3.x 会在编译阶段报错。反过来Spring Boot 2.7 在 JDK 17 下虽然能编但很多老模板里的spring-boot-starter-tomcat和 JSP 相关配置会出奇奇怪怪的兼容问题。所以先确认版本再决定要不要换 JDK。顺带说一个技术点Spring Boot 默认优先使用 CGLIB 代理而不是 JDK 动态代理。很多简易后台的 Service 没有单独抽接口这在 Spring Boot 里能被正常代理原因就是 CGLIB 针对类做子类化。这一点在答辩时经常被老师拿出来问你在后续加切面日志时也会遇到它。2.2 核对前端脚手架Vue 2 的 Vue CLI 还是 Vue 3 的 ViteAnt Design Vue Pro 有多个历史形态老一批的毕设模板基于 Vue 2 Vue CLI依赖里会出现vue-cli-service和node-sass新一些的模板基于 Vue 3 Vite依赖里会出现vite和vitejs/plugin-vue。这两种项目的启动命令和代理配置位置完全不同。cd frontend cat package.json判断方法简单scripts.dev里是vue-cli-service serve就走 Vue CLI是vite就走 Vite。老模板里的node-sass是重灾区Node 16 以下比较稳妥Node 18 以上经常在npm install阶段编译失败。新模板则用 Node 16 或 18 都行个别依赖需要 Node 16 以上的 API所以太老反而也不行。给你一个粗略对照表前端依赖特征前端脚手架推荐 Node 版本代理配置文件vue-cli-servicenode-sassVue CLI14.x 或 16.xvue.config.jsvitevitejs/plugin-vueVite16.x 或 18.xvite.config.js这一步不要跳很多同学上来就npm install结果被node-sass的安装日志折磨一小时。先看依赖再决定要不要用 nvm 切换 Node 版本能省掉大半麻烦。2.3 看懂后端和前端目录才能知道动手改哪里简易后台管理系统的代码量不大但结构是固定的。后端一般长这样backend/src/main/java/cn/xxx/admin/ common/ 通用返回体 Result、分页对象、全局异常处理 config/ MyBatis 配置、Cors 配置、JWT 配置 controller/ REST 接口层 service/ 业务逻辑层 mapper/ MyBatis Mapper 接口 entity/ 数据库表映射对象 backend/src/main/resources/ mapper/ Mapper XML主要是原生 SQL application.yml前端的关键路径是frontend/src/ api/ 接口封装按模块拆文件 layout/ 后台整体框架侧边栏和顶栏 router/ 路由配置和路由守卫 store/ Vuex 或 Pinia存 token 与用户信息 views/ 页面组件 utils/ request.js 请求封装等工具我一般会按这个顺序去读工程先看pom.xml和package.json再看application.yml然后看router/index.js最后看store/modules/user.js。只要把这四个文件看懂就基本能描述清楚这个系统的登录流程和权限控制方式答辩时被问到“代码结构”也不会心虚。3. 把前后端真正跑在一起数据库、后端、前端三级启动3.1 先找到 SQL 初始化脚本建库并改数据库密码很多 zip 里会带一个sql/或doc/目录里面放着建表脚本和假数据。没有脚本的话你连登录页都到不了。执行顺序是先找 SQL再建库最后改后端配置。find . -iname *.sql | head -20 mysql -uroot -p -e CREATE DATABASE IF NOT EXISTS admin_system DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; mysql -uroot -p admin_system sql/init.sql第一句用于确认哪些 SQL 是建表哪些是示例数据。第二句是显式创建数据库因为部分原作者的脚本没有CREATE DATABASE语句直接导入会报“没有选择数据库”。第三句把表结构和初始用户导入。接着改后端配置server: port: 8080 servlet: context-path: /api spring: datasource: url: jdbc:mysql://localhost:3306/admin_system?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/Shanghai username: root password: 你自己的密码 driver-class-name: com.mysql.cj.jdbc.Driver mybatis: mapper-locations: classpath:mapper/*.xml configuration: map-underscore-to-camel-case: true jwt: secret: 随便换一串比较长的字符串 expire-hours: 24注意几个参数context-path: /api表示后端所有接口都挂在/api前缀下这会影响前端代理的写法characterEncodingutf8是为了让中文不乱码map-underscore-to-camel-case保证数据库里的create_time能自动映射成 Java 的createTime。如果你拿到的是 MyBatis-Plus 版本把mybatis换成mybatis-plus即可。3.2 配置前端代理让前端请求打到后端前端页面访问的接口地址一般不是http://localhost:8080而是/api/...这层转发由开发服务器代理完成。Vue CLI 老模板在vue.config.js里配置// vue.config.js const { defineConfig } require(vue/cli-service) module.exports defineConfig({ devServer: { port: 8000, proxy: { /api: { target: http://localhost:8080, changeOrigin: true, pathRewrite: { ^/api: } } } } })Vite 新模板的写法稍有差别但效果一样// vite.config.js import { defineConfig } from vite export default defineConfig({ server: { port: 8000, proxy: { /api: { target: http://localhost:8080, changeOrigin: true, rewrite: path path.replace(/^\/api/, ) } } } })这里最需要想清楚后端context-path是/apiController 里的RequestMapping写的又是/login经过 Vue 开发服务器代理后接口请求变成了/api/login。代理把/api剥掉再交给http://localhost:8080此时后端 context-path 又补了一个/api于是最终访问/api/login链路正好闭合。如果后端没有设置context-path而是直接在 Controller 的RequestMapping里写了/api那你就不应该重写/api直接把 target 指到后端即可。判断方式很简单登录成功后打开浏览器 Network看请求 URL 是不是带了两层/api/api如果是就说明代理和后端前缀重复了。3.3 后端启动、前端启动再用登录接口验证链路cd backend mvn spring-boot:run启动后看到Tomcat started on port(s): 8080就证明后端服务已经起来。然后新开一个终端cd frontend npm install npm run dev看到类似App running at: http://localhost:8000的提示后浏览器访问这个地址。正常的登录流程是打开登录页输入管理员账号密码拿到 Token跳转到首页。如果登录时验证码报错先看后端日志里有没有 Redis 连接异常。很多前后端分离的登录验证码是把图片验证码的答案暂存在 Redis 里本机没起 Redis 服务验证码接口就会一直报错。检查方式redis-cli ping只要能回PONG就说明 Redis 在线。如果项目里连缓存都没有验证码可能就是纯前端生成跟后端无关那问题往往出在后端接口的跨域或代理配置上。到这一步链路算真正通了接下来才是改造功能。4. 把它改造成能答辩的模块从一组权限表到一个新业务页面4.1 权限模型为什么老师爱问三张表而包里常常只有一张用户表简易后台管理系统最常见的简化操作是在sys_user表里加一个role字段比如role admin登录后根据字符串判断角色。这种设计能跑但答辩时老师几乎必问“如果你有新角色怎么办”所以至少要把用户-角色-菜单这条路理顺。一组最小可用表结构如下CREATE TABLE sys_user ( id BIGINT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) NOT NULL, password VARCHAR(100) NOT NULL, status TINYINT DEFAULT 1, create_time DATETIME DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE sys_role ( id BIGINT PRIMARY KEY AUTO_INCREMENT, role_code VARCHAR(50) NOT NULL, role_name VARCHAR(50) NOT NULL ); CREATE TABLE sys_user_role ( user_id BIGINT, role_id BIGINT ); CREATE TABLE sys_menu ( id BIGINT PRIMARY KEY AUTO_INCREMENT, parent_id BIGINT DEFAULT 0, name VARCHAR(100), path VARCHAR(200), permission VARCHAR(100) ); CREATE TABLE sys_role_menu ( role_id BIGINT, menu_id BIGINT );这里的核心思想是用户不直接拥有菜单用户通过user_role关联到角色角色再通过role_menu关联到菜单。查询某个用户看到的菜单就是两条关联表 join 的事情。这样改完之后你就能在演示时说“新增一个角色不需要改代码只要在菜单表里配置权限”。如果时间紧张至少把sys_user_role加上并把登录返回的结果从原来的字符串角色改成角色代码数组。前端根据角色数组做按钮级权限控制老师问起来也有得说。4.2 后端新增一个公告管理模块的最小四件套新模块无论叫公告管理、消息管理还是校园资讯管理后端套路是一致的。以常见的 MyBatis-Plus 工程为例先写实体Data TableName(bus_announcement) public class Announcement { TableId(type IdType.AUTO) private Long id; private String title; private String content; private Integer status; private LocalDateTime createTime; }这段代码的作用是让 ORM 知道bus_announcement表和这个 Java 对象的字段对应关系。TableId(type IdType.AUTO)表示主键自增TableName里写数据库真实表名如果字段名和表字段完全一致就不需要额外写TableField。再写 MapperMapper public interface AnnouncementMapper extends BaseMapperAnnouncement { }一个空接口就能拥有增删改查和分页查询能力这是 MyBatis-Plus 提供的 BaseMapper 内置方法。注意接口上要加Mapper注解或者在启动类上加MapperScan扫描包二选一即可。然后是 Service 和 ControllerService public class AnnouncementService { Autowired private AnnouncementMapper announcementMapper; public IPageAnnouncement pageList(int page, int limit) { PageAnnouncement p new Page(page, limit); return announcementMapper.selectPage(p, new LambdaQueryWrapperAnnouncement() .orderByDesc(Announcement::getCreateTime)); } }RestController RequestMapping(/announcement) public class AnnouncementController { Autowired private AnnouncementService announcementService; GetMapping(/page) public ResultIPageAnnouncement page(RequestParam(defaultValue 1) Integer page, RequestParam(defaultValue 10) Integer limit) { return Result.ok(announcementService.pageList(page, limit)); } }这里有两个地方值得解释LambdaQueryWrapper可以避免拼接 SQL 字符串orderByDesc(Announcement::getCreateTime)等价于ORDER BY create_time DESC它用的是方法引用编译期就能发现字段名字错误。Controller 返回的Result是后台系统里的统一返回体一般包含code、message、data三个字段如果你拿到的工程没有就在common包里自己补一个否则前端请求封装会解析不出来。前文提过 Spring Boot 默认使用 CGLIB 代理所以这里的AnnouncementService即使没有接口也能被Transactional、日志切面等机制代理。答辩时如果有人问“你的 Service 为什么没有接口”可以从这里解释而不是当场愣住。4.3 前端加页面、加接口、加路由菜单后端接口写完后前端需要做三件事封装 API、写页面、注册路由。先在src/api/下新建announcement.jsimport request from /utils/request export function pageAnnouncement(params) { return request({ url: /announcement/page, method: get, params }) }这个文件把后端的/announcement/page接口封装成pageAnnouncement函数页面里不需要关心 Token 怎么加、请求超时怎么处理一切由request工具统一处理。然后写一个列表页面template a-card title公告管理 a-table :data-sourcelist :columnscolumns row-keyid :loadingloading / /a-card /template script setup import { ref, onMounted } from vue import { pageAnnouncement } from /api/announcement const list ref([]) const loading ref(false) const columns [ { title: 标题, dataIndex: title }, { title: 状态, dataIndex: status }, { title: 创建时间, dataIndex: createTime } ] onMounted(async () { loading.value true try { const res await pageAnnouncement({ page: 1, limit: 10 }) list.value res.data.records } finally { loading.value false } }) /script这段代码用了 Vue 3 的组合式 APIref定义响应式数据onMounted在页面加载后请求接口。Ant Design Vue Pro 的表格组件只负责接收>{ path: /announcement, component: Layout, children: [ { path: index, name: Announcement, component: () import(/views/announcement/index.vue), meta: { title: 公告管理, icon: notification } } ] }Ant Design Vue Pro 的侧边栏菜单是由路由表递归生成的所以路由加进去菜单就会自动出现。如果原工程用了动态路由也就是登录后根据后端返回的菜单生成路由那么还需要把这条路由配置加到后端菜单表里前端路由只留一个“通配”即可。判断方法是看router/index.js里有没有addRoute关键字有就说明是动态路由。5. 避坑从 Spring Boot 启动到 Vue 打包进后端的 5 个拦路坑5.1 后端一直报Failed to configure a DataSource现象执行mvn spring-boot:run后控制台输出Failed to configure a DataSource: url attribute is not specified and no embedded datasource could be configured.随后应用退出。原因Spring Boot 自动配置机制在 classpath 里发现数据库驱动于是触发DataSourceAutoConfiguration但你的application.yml里没有可用的数据源连接信息。常见于 zip 包里没带application.yml或者 yml 文件名不是application例如原来是application-dev.yml但启动时没有指定devprofile。解决先确认配置文件是否真的存在再确认启动环境。临时做法是启动时指定环境mvn spring-boot:run -Dspring-boot.run.profilesdev如果想彻底解决就把application-dev.yml里的数据源配置合并到application.yml并确保spring.datasource.url、username、password三项都有值。这个报错也经常被老师拿来问“Spring Boot 自动装配原理”你可以顺着说启动时的自动配置类会根据条件注解判断只要有DataSource相关的类并且没有手动排除它就会尝试创建连接池。5.2 前端npm install翻车node-sass 补不上现象执行npm install时窗口里出现gyp ERR! stack Error: EACCES: permission denied或者node-sass在下载二进制文件时卡住然后失败。原因老式 Ant Design Vue Pro 模板用了node-sass这是一个需要编译原生模块的包。Node 版本太高时它找不到对应版本的预编译二进制只能现场编译而编译环境往往缺少 Python、C 编译工具或者权限不够。解决切换到 Node 16再删除node_modules和package-lock.json后重新安装node -v nvm install 16 nvm use 16 rm -rf node_modules package-lock.json npm install如果你在安装又卡住了可以先设置镜像再装不要反复 CtrlC否则会产生半截的node_modules下次执行时问题更隐蔽。这个坑属于典型的“环境问题”不是代码逻辑问题但每年都有大量项目在这里翻车。5.3 登录成功后一刷新页面就回到登录页现象在登录页输入账号密码后能正常进入首页但只要按 F5 刷新马上跳回登录页查看浏览器开发者工具发现 localStorage 里明明有 Token。原因Ant Design Vue Pro 的登录状态不只存在 localStorage还会初始化到 Vuex 或 Pinia。刷新后 store 被重建如果store/modules/user.js里初始 Token 没有从 localStorage 读取而是写死为空字符串路由守卫一看“没有 Token”就把人拦回登录页。解决在 store 的 state 初始化阶段读取本地缓存const token localStorage.getItem(admin_token) || 同理用户信息也要有一个持久化策略。最简单的做法是登录成功后把用户信息也放进 localStorage刷新后先判断 Token再判断用户信息为空就去调getUserInfo接口。这样既避免每次刷新都请求一次接口也保证页面重新加载时角色权限不过期。5.4 前端请求路径出现两层/api后端接口 404现象浏览器 Network 面板里看到请求 URL 是http://localhost:8000/api/api/login后端明明启动成功却一直返回 404。原因后端context-path设成了/api前端代理又把/api重写掉了导致代理向后端转发的路径是对的但 Controller 里的RequestMapping没有包含/api于是拼不出正确接口。更常见的是后端 Controller 写了/api/login前端代理也保留/api最后后端收到/api/api/login。解决统一前缀只保留一层。以后端为准如果后端 Controller 的RequestMapping已经带/api前端代理就不要剥掉/api如果后端靠context-path: /api统一加前缀前端代理才需要pathRewrite剥离一层。这个坑适合用一张小表记录避免每次换新电脑都盲调。后端接口实际路径前端代理 rewrite转发后效果Controller 里有/api/login不 rewrite到后端/api/loginController 里是/logincontext-path 是/apirewrite 去掉/api到后端/api/login5.5 Vue 打包放进 Spring Boot 后刷新 404现象执行npm run build得到dist目录把里面的文件复制到backend/src/main/resources/static放进 Spring Boot 后访问http://localhost:8080/能打开首页但点击某个子菜单再刷新就变成白页或 404。原因Vue Router 默认是 history 模式路由路径是真实的浏览器路径比如/system/user。Spring Boot 的静态资源处理器只认识index.html和真实存在的文件遇到/system/user就认为没有这个资源于是返回 404。解决本地演示最省事的方法是改成 hash 模式把createWebHistory改成createWebHashHistory刷新后不会 404代价是路径里多一个#/。如果你想保留 history 模式就要在后端加 forward 规则把非静态资源路径转发到index.htmlController public class ForwardController { GetMapping(value {/{path:[^\\.]*}, /login, /dashboard, /system/**}) public String forward() { return forward:/index.html; } }这段代码的作用是把前端路由路径转交给index.html由 Vue Router 接管页面渲染。注意[^\\.]*是为了排除静态资源后缀比如.js、.css等。这个坑在答辩前最后一天最容易遇到建议提前打包测试而不是现场改。6. 答辩前最后三招初始化数据、接口文档、默认密码6.1 加一份可以直接演示的初始化数据脚本答辩演示最怕打开页面发现列表是空的所以我会单独做一个demo_data.sql里面准备两个角色账号和 20 条以上业务数据。执行一遍恢复环境mysql -uroot -p admin_system docs/sql/demo_data.sql这样即使现场演示把数据改乱了也能在几分钟内恢复。写脚本时注意把时间字段设为近期时间太旧的数据在表格排序显示时看起来不真实。6.2 把接口文档亮出来而不是在 IDEA 里翻代码很多老师会问你“系统里有哪些接口、参数是什么”。与其带着老师看代码不如直接集成接口文档。Spring Boot 2 工程常见做法是加 Knife4j 依赖Spring Boot 3 工程则用 springdoc 的 starter。启动后浏览器打开/doc.html所有 Controller 接口、参数说明、返回示例都在页面上演示时非常加分。如果没时间集成至少给每个 Controller 的类名上加一行Api或Tag注解让它能显示中文模块名。接口文档不用写得很全把登录、用户管理、你新增的公告管理这几个核心接口写清楚就足够应付问答了。6.3 我最后会做的一件事每次答辩前我都先改掉系统默认密码并且把 JWT 密钥换掉。这看起来是小事但老师在你的电脑上第一次打开系统时多半会顺手点开用户表看有没有admin/123456这种裸奔账号。改掉之后我会重新打包一次 project压缩包命名带上日期和版本信息避免把旧包里的数据库密码留在演示环境里。这套流程帮助我把好几个原本乱糟糟的毕设包救回来也让“简易后台管理系统”这种看起来普通的题目实际答辩时长多出不少可讲内容。希望帮到你。本文还有配套的精品资源点击获取
返回列表