资讯动态

SpringBoot+Vue+MySQL个人理财系统毕设开发全流程实战

发布时间:2026/10/9 3:08:20 来源:尧图企业网站定制
一到毕业季最头疼的就是毕设选题。我当年选题目的时候纠结了很久后来选择做一个SpringBootVueMySQL 个人理财系统平台从选题到答辩整个周期大概花了两个月。这个题目回头来看非常“划算”技术栈是最主流的前后端分离组合功能够用不夸张论文素材也容易组织还能在报表、图表这些地方额外加亮点。这篇文章把我从环境搭建、数据库设计、前后端编码到部署上线的完整过程复盘了一遍包含不少踩坑记录希望对同样在做管理系统类毕设的同学有帮助。1. 毕设选题个人理财系统为什么值得做1.1 题目的覆盖面与加分空间很多学校毕设要求“有完整的业务流程 数据库设计 Web展示”而这个题目完美命中。个人理财系统不是简单增删改查它天然包含用户认证、账目管理、分类统计、预算预警、可视化报表等模块。哪怕只实现最基础的记账功能也足以覆盖SpringBoot和Vue的核心用法如果学有余力还可以把预算超支提醒、账单导入导出、定时统计等做成加分项。我觉得最实际的一点是你不需要找团队、不需要真实用户所有的数据自己造所有的流程自己设计工作量完全可控。相比电商、外卖这些动不动就要处理高并发、多角色的系统理财系统业务边界清晰适合一个人独立完成。和导师沟通的时候你可以明确说“这个题目会有用户模块、记账模块、统计报表模块”导师一听就知道你是认真的。1.2 核心功能怎么规划先做骨架再加肉我建议功能规划分三层。第一层是必备功能包括注册登录、密码加密存储、记账收入/支出、账目分类管理、账单列表的分页和筛选。第二层是提升体验的功能包括预算设置、月度统计图表、按分类汇总、账户余额管理。第三层是展示功能比如年度收支对比、导出Excel、最近消费趋势图。导师通常更看重的不是功能数量而是数据流向是否合理表结构是否规范所以哪怕只有前两层也已经是一个完整的系统。我实际做的版本里登录后第一个页面就是仪表盘展示本月收入、本月支出、结余、预算使用率下方是近7天收支趋势和分类占比饼图。这套设计看起来“高级”但实现起来本质就是几个统计SQL加上ECharts图表的渲染。对于展示型毕设来说视觉效果比复杂的业务逻辑更能让老师眼前一亮。1.3 SpringBootVueMySQL这个组合的底气为什么我坚持推荐这个组合第一生态成熟资料极多。你在配置或部署时遇到任何问题几乎都能搜到对应解决方案而且很多学校教材、视频课都以这三件套为例指导老师也不会陌生。第二前后端分离架构本身就符合当前行业普遍做法答辩时你可以直接说“前端使用Vue脚手架搭建后端提供RESTful API通过Axios交互”这一句话就是完整加分点。第三MySQL是目前教程最多的关系型数据库安装、备份、恢复资料丰富不容易在数据层卡住。有人可能担心SpringBoot版本太新导致各种坑这个问题我在下一部分详细讲实际上用固定的稳定版本就能规避大部分问题。2. 环境搭建阶段版本和配置问题全记录2.1 SpringBoot版本太高引发的连锁反应我当时图省事直接新项目拉了个最新版本的SpringBoot结果是3.x版本默认依赖Java 17而我的JDK还是8。启动直接报错各种依赖不兼容连springfox的Swagger配置都跑不起来。后来我把SpringBoot降到2.7.18JDK用1.8所有依赖全部匹配稳定版本一次编译通过。这里给一个可复用的选型参考SpringBoot 2.7.18 JDK 1.8 MyBatis-Plus 3.5.3 jjwt 0.9.1 Maven 3.8。如果你的学校没指定Java版本那这套组合是最稳的。如果非要用SpringBoot 3.x就必须用Java 17同时很多老版本的第三方依赖库需要升级不建议毕设阶段折腾兼容性问题。创建项目的时候我推荐直接去 Spring Initializr 选择“2.7.18”版本依赖勾选Web、MySQL Driver、Lombok。注意Lombok一定要选它能省掉大量getter/setter代码让实体类看起来很清爽还能在论文里写“使用Lombok简化开发”。2.2 Vue安装与npm环境准备的经典坑前端环境我用了Vue 3 Vite因为Vite启动速度快而且新项目模板比Vue CLI更干净。但Vite同样有Node版本要求我在配置时发现如果Node版本过旧npm create vuelatest会报错或卡住。建议直接安装Node 16.20或18以上的长期支持版本安装完成后用node -v确认。真正常见的坑在于npm下载依赖太慢或者莫名其妙报Error: certificate has expired。我当时处理办法是给npm换成本地镜像源然后清掉缓存重新安装。具体命令npm config set registry https://registry.npmmirror.com npm cache clean --force npm install如果项目里已经存在node_modules目录安装新的依赖后依然有奇怪报错直接删掉整个目录和package-lock.json重新npm install。这一步能解决90%的依赖混乱问题。还有个小技巧通常在npm create vue生成的模板中组件使用script setup语法比起传统export default更简洁也更适合毕设项目里快速写页面。2.3 MySQL安装、初始化与建库注意事项MySQL最经典的问题是服务启动失败和密码设置不生效尤其在新手安装时容易漏掉“以管理员身份运行”这一步。我用的是MySQL 5.7.44安装配置时注意几个细节选择“Server only”可以减少无用组件安装完成后要在环境变量PATH里加入MySQL的bin目录初始化数据库实例之前先创建好配置文件my.ini指定字符集为utf8mb4。[mysqld] port3306 basedirC:/Program Files/MySQL/MySQL Server 5.7 datadirC:/Program Files/MySQL/MySQL Server 5.7/data character-set-serverutf8mb4在my.ini里指定字符集非常重要否则Java连接MySQL时中文可能会变成问号。初始化服务后用命令行登录执行ALTER USER rootlocalhost IDENTIFIED BY 你的密码;确保密码正确。如果使用的是MySQL 8.x注意驱动版本要用com.mysql.cj.jdbc.Driver并在URL中加上useSSLfalseserverTimezoneAsia/Shanghai。建库建表时我习惯在Navicat里手动执行SQL脚本然后把建表语句单独存成init.sql这样论文附录和部署文档都能直接用也方便老师查看数据结构。3. 数据库设计理财系统的表结构与关键SQL3.1 核心表结构设计思路理财系统的表设计关键是处理好用户、账户、分类、交易流水和预算之间的关系。我设计了5张主表整体符合第三范式但又不过度拆分下面这张表可以直接参考。表名作用关键字段tb_user用户信息id, username, password, nickname, create_timetb_account账户信息id, user_id, account_name, balance, typetb_category收支分类id, user_id, category_name, type(1收入/0支出)tb_transaction交易流水id, user_id, account_id, category_id, amount, type, remark, trans_datetb_budget月预算id, user_id, category_id(可空), budget_amount, month唯一要注意的是所有涉及用户数据的表都加上user_id字段这样后续所有查询都可以通过where user_id ?做隔离既保证用户数据安全也便于在答辩时解释“多用户数据权限设计”。交易表是核心字段除了金额和类型外建议同时记录account_id和category_id因为账目要关联到“从哪个账户花的”以及“花在哪个分类上”。我在设计时为trans_date建了索引因为统计报表几乎都是按时间范围查询没索引的时候数据量只要到几千条查询就会明显变慢。3.2 月度收支统计的SQL优化统计报表里最常用的是“统计某月的总收入、总支出”。这个需求用一条聚合SQL就能完成。SELECT SUM(CASE WHEN type 1 THEN amount ELSE 0 END) AS total_income, SUM(CASE WHEN type 0 THEN amount ELSE 0 END) AS total_expense FROM tb_transaction WHERE user_id 1 AND trans_date BETWEEN 2024-05-01 AND 2024-05-31;分类占比的统计则要按category_id分组关联分类表查名称SELECT c.category_name, SUM(t.amount) AS total_amount FROM tb_transaction t JOIN tb_category c ON t.category_id c.id WHERE t.user_id 1 AND t.type 0 AND t.trans_date BETWEEN 2024-05-01 AND 2024-05-31 GROUP BY t.category_id;在实际项目中我发现一个容易忽略的点时间范围过滤时BETWEEN两个日期字符串会丢失最后一天的零点到二十三点的数据。更稳妥的做法是trans_date 2024-05-01 AND trans_date 2024-06-01这样天然覆盖完整月。统计接口返回的数据结构可以设计成Map或者用一个VO类来接收。如果你的项目里用了MyBatis-Plus也可以直接用QueryWrapper配合selectMaps避免写大量XML。3.3 数据完整性、索引与事务取舍在设计表结构时不要过度设计外键。我一开始给tb_transaction的user_id、category_id都加了物理外键后来删记账数据时频繁报错联动删除很麻烦。最佳实践是保留逻辑关联不加物理外键在Java代码中维护引用关系。这样既不影响查询性能也方便做删除操作。事务处理方面删除一条账单时如果需要同步更新账户余额那么容易出现“账单删了余额没变”的问题。解决办法是在Service层方法上加上Transactional注解确保两步操作要么都成功要么都回滚。举例如下Transactional public void deleteTransaction(Long id) { Transaction tx transactionMapper.selectById(id); // 恢复账户余额 Account account accountMapper.selectById(tx.getAccountId()); if (tx.getType() 1) { account.setBalance(account.getBalance().subtract(tx.getAmount())); } else { account.setBalance(account.getBalance().add(tx.getAmount())); } accountMapper.updateById(account); transactionMapper.deleteById(id); }这里还有个小建议金额字段不要用float或double容易出现0.10.2精度丢失的问题表字段用decimal(10,2)Java实体类用BigDecimal虽然开发时多一点转换但这是财务数据的基本要求答辩时提一句能加分。4. 后端实现从登录鉴权到统计接口4.1 基于JWT的登录流程和拦截器配置个人理财系统的用户登录我没有用传统的Session而是选择JWT Token这样前后端分离更彻底也让答辩时有个可聊的“技术亮点”。整体流程是用户登录后后端校验用户名密码生成一个Token返回给前端前端把Token存在LocalStorage里之后每次请求都在Header中携带Authorization: token后端通过拦截器校验。JWT工具类主要包含生成和解析两个方法。public class JwtUtils { private static final String SECRET your-secret-key; public static String generateToken(String username) { return Jwts.builder() .setSubject(username) .setExpiration(new Date(System.currentTimeMillis() 1000 * 60 * 60 * 12)) .signWith(SignatureAlgorithm.HS256, SECRET) .compact(); } public static String parseToken(String token) { return Jwts.parser() .setSigningKey(SECRET) .parseClaimsJws(token) .getBody() .getSubject(); } }拦截器实现上我用HandlerInterceptor的preHandle方法先排除登录和注册接口再对携带Token的请求校验身份校验失败直接返回401由前端统一跳回登录页。需要说明的一点是JWT的密钥不能写死在一个类里最好放到application.yml配置中虽然毕设项目演示没多大风险但这能体现你了解配置分离的规范。4.2 记账业务接口的CRUD与校验记账的核心接口有四个新增账单、修改账单、删除账单、分页查询账单。新增和修改都要做参数校验金额必须大于0类型必须是0或1日期不能为空。另外新增账单时如果涉及账户余额尽量在同一事务里完成两条数据更新。我建议Controller层不要写太多业务逻辑统一使用Result返回对象结构为{ code: 200, message: success, data: ... }。前端拿到code再判断是否成功这样接口返回比较规范。分页查询用MyBatis-Plus的Page对象前端传入pageNum和pageSize返回总记录数和当前页数据。这里补充一个开发中容易踩的坑在编辑账单时如果用户改了金额后端需要重新计算对应账户余额变化。有些同学会直接更新账单结果账户余额没同步。正确做法是先读取原账单求出差额再更新账户余额最后更新账单。4.3 统计报表接口的聚合查询实践统计接口主要给仪表盘用包含三类数据本月收支汇总、近7天收支趋势、分类占比。近7天趋势可以写一条按天分组的SQL注意要补全没有数据的那几天否则前端图表会缺少坐标点。我当时的处理方式是后端先查询出已有的日期和金额然后在Java中补缺失日期统一组装成前端需要的格式。分类占比接口返回的数据结构如下[ { name: 餐饮, value: 680.00 }, { name: 交通, value: 220.00 }, { name: 购物, value: 1500.00 } ]这个结构正好对应ECharts饼图中的data字段前端不用做任何二次转换非常方便。统计接口的性能一般都不需要过度优化只要查询走索引几千条数据几乎是毫秒级返回。4.4 数据访问层选型MyBatis-Plus还是Spring Data JPA在毕业设计里数据访问层我推荐用MyBatis-Plus因为它在MyBatis基础上增强了单表CRUD功能几乎不用写SQL。比如分页只需要selectPage(new Page(pageNum, pageSize), queryWrapper)构造查询条件只需要lambdaQuery()。这些代码写在Service层里可读性比XML高很多也方便论文里展示“核心代码”。但是复杂统计查询还是建议自己写SQL因为MyBatis-Plus的QueryWrapper应对多表关联和分组聚合时会很别扭。混合使用的策略是单表操作走BaseMapper自带方法多表查询写Mapper接口方法配上Select注解直接写SQL既直观又省去XML配置。如果你的项目需要大量多表查询也可以保留XML目录在application.yml里配置mapper-locations两种方式我都在项目里用过两者兼顾最顺手。5. 前端实现Vue项目从创建到图表可视化5.1 项目创建、路由和目录组织前端我使用Vue 3 Vite Element Plus Pinia Vue Router这是目前比较主流的一套组合。创建项目之后我按功能划分了目录views放页面组件components放可复用组件router放路由api放接口请求。目录结构清晰会让后期答辩展示好讲很多导师问起工程结构时你可以直接说“按职责划分页面组件和业务组件分离”。路由配置里需要重点处理“未登录访问页面”的问题。我在Vue Router的beforeEach全局守卫中判断本地是否有Token如果没有就强制跳转登录页。这段逻辑是所有管理系统的标配代码非常简单router.beforeEach((to, from, next) { const token localStorage.getItem(token) if (to.path ! /login !token) { next(/login) } else { next() } })登录页和主页Layout分开主页左侧菜单放仪表盘、账目管理、预算设置等右侧是内容区域。这样结构上已经是一个“平台”的样子而不是简单的单页。5.2 axios封装和登录态维持axios封装是前端工程里很重要的一步。我在src/api/request.js中创建了一个axios实例设置baseURL为/api并在请求拦截器中自动加上Token响应拦截器中统一处理401。service.interceptors.request.use(config { const token localStorage.getItem(token) if (token) { config.headers[Authorization] token } return config }) service.interceptors.response.use( res { if (res.data.code 401) { localStorage.removeItem(token) window.location.href /login } return res.data }, err { return Promise.reject(err) } )这样做的好处是所有接口都不用重复写Token逻辑也不用手动处理错误。我在后端接口返回结构里统一包含code字段前端拦截器聚焦判断code而不是判断HTTP状态码因为后端业务异常也会返回HTTP 200。5.3 从静态数据到ECharts图表的接入图表是个人理财系统的灵魂。我使用ECharts 5在组件中先准备图表容器div refchartRef styleheight: 300px/div然后通过echarts.init初始化。如果数据是后端来的建议封装一个方法调用接口拿数据setOption更新图表。实际开发中的经典问题是图表容器还没有渲染完成就初始化导致图表宽度为0。解决方式是用nextTick或者在容器可见后再调用init我通常是让仪表盘组件挂载后在onMounted里请求数据并渲染。近7天趋势我用折线图分类占比我用饼图这两类图足以覆盖常见的财务报表需求。如果想把项目做得更细致一点可以再增加柱状图用来对比支出和收入整体视觉效果更强。5.4 组件复用的几个实践细节个人理财系统中账单列表在多个页面都可能出现所以我拆成了TransactionTable组件接收userId和queryParams作为props点击分页时向父组件抛事件父组件再重新请求数据。这个模式初期写着麻烦但到后面页面多了收益非常明显。另外要分享的是“日期范围选择”的处理。Element Plus的el-date-picker返回的数组是时间戳而后端需要字符串格式我在提交前用dayjs做了格式化再放进请求参数里。这是一个很小的点但很多新手会在这里卡住传参总是不对导致后端查询结果为空。6. 毕设论文与答辩准备写给还没动手的同学6.1 论文结构与“非技术”篇幅的写作学校的论文模板通常要求包括绪论、需求分析、系统设计、系统实现、系统测试、总结与展望。这部分最容易写的其实是“系统设计”因为你完全可以把数据库表结构、接口设计、页面设计用图表展示出来每张图配一段说明篇幅就出来了。我写论文时的一条经验是需求分析不要只写“用户可以记账”要细化成功能用例表比如“用户可以新增收入输入金额、日期、分类系统自动更新账户余额”这样每一条都是一段内容。类似的还有非功能性需求说明系统需要支持并发、响应时间不超过2秒、数据准确率100%等这些东西不一定真的做了性能测试但能让论文显得严谨。6.2 测试用例和截图如何组织系统测试章节是最好写也最容易拿分的部分。我按“登录模块、账单管理模块、预算模块、统计模块”分别列出测试用例表每行包括测试编号、测试步骤、预期结果、实际结果、是否通过。然后对有代表性的操作附上截图比如新增账单成功后列表刷新、支出超预算时红色预警提示。这里建议提前准备脚本化的测试数据不要等写论文时临时注册一堆用户。我当时的做法是建了一批测试用户每个用户有几十条交易数据覆盖面广截图时效果更好。测试数据也顺便验证了统计接口的正确性。6.3 答辩提问预测和材料准备答辩老师经常问的有几个问题为什么选这个技术栈、数据表怎么设计的、登录是怎么保持状态的、ECharts图表数据是怎么来的、设计过程中遇到的最大困难是什么。这些问题我提前写在了答辩PPT备注里并且准备了项目运行demo答不上来的时候直接演示效果远好于背概念。有一个容易忽略的点答辩当天一定要准备一个演示账号密码要简单进入系统后马上打开仪表盘页面。因为仪表盘是系统最亮眼的页面先展示它后面老师注意力就会集中在你如何实现这些图表上而不是揪着某个细节反复问。7. 部署与交付本地联调和服务器上线的操作细节7.1 前后端联调的环境配置在本地开发阶段我让后端跑在8080端口前端跑在5173端口前端通过Vite代理转发解决跨域问题。在vite.config.js中配置server: { proxy: { /api: { target: http://localhost:8080, changeOrigin: true } } }后端Controller层的请求路径统一以/api开头这样前端所有请求都会命中代理规则不会出现跨域报错。如果用的是Vue CLI则在vue.config.js里配置devServer.proxy原理相同。联调阶段最容易碰见的问题是后端返回的JSON字段命名风格不同我统一在后端配置了spring.jackson.property-naming-strategy SNAKE_CASE让数据库下划线字段自动变成前端驼峰命名省去很多手工转换。7.2 后端打包与前端build的注意事项后端打包前一定要确认application-prod.yml中的数据库连接、文件路径等配置不能写死本机密码。实际打包时执行mvn clean package -DskipTests生成target目录下的jar包用java -jar启动即可。这里有一个容易让人困惑的点SpringBoot多环境配置文件项目里最好有application-dev.yml和application-prod.yml两个环境启动参数指定--spring.profiles.activeprod演示时来回切换环境非常方便。前端构建执行npm run build产物在dist目录。构建时需要改一下资源路径Vite默认使出的是绝对路径/assets/...部署在子目录时会显示不了我习惯在vite.config.js里设置base: ./这样生成的HTML引用的资源都是相对路径部署到哪里都不会错。7.3 上线演示环境的搭建流程对于毕设答辩可以只部署在本地或者虚拟机也可以租云服务器上线。如果选服务器我建议用一个轻量级Linux实例安装JDK、MySQL、Nginx。这里给出常见流程把后端jar包传到服务器使用nohup java -jar system.jar log.out 21 启动前端把dist目录下的文件放到Nginx的html目录然后配置反向代理将/api请求转发到http://localhost:8080这样用户访问Nginx的80端口就能同时获得前端页面和后端接口。Nginx反向代理的关键配置如下server { listen 80; location / { root /usr/share/nginx/html; index index.html; } location /api/ { proxy_pass http://localhost:8080; } }这个方案的好处是前后端部署在同一台服务器对外只暴露一个端口演示时不用讲解太多网络细节。如果不想用服务器通过Windows自带的mstsc远程桌面、或者在内网环境下直接运行jar包也可以完成答辩展示。部署文档在最后阶段建议搭配截图按顺序列出“启动数据库、启动后端、启动前端、访问地址”四步老师跟着步骤能自己跑起来这种交付质量会明显高于只交一个源码压缩包。除了上述技术细节我实际做完这个项目还有几个个人感受。第一个是不要追求代码量多而是要把每条链路的逻辑讲通从登录到记账再到统计每一步的数据流向要自己能口述出来。第二个是准备一份干净的数据字典把每张表每个字段的注释写清楚后期写论文和答辩被追问时直接打开数据字典就能回答。第三个也是我最想提醒的毕业设计真正耗时间的往往不是写代码而是环境配置和部署联调至少提前一周开始做部署环境测试别等到答辩前一晚才第一次启动jar包和前端构建产物否则一个问题就能让你一晚上睡不着。如果你决定做这个题目按我上面整理的顺序走一遍整个过程会顺很多。

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

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

免费获取报价 →
↑