ARTICLE DETAIL

资讯详情

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

SpringBoot+Vue+MySQL财务管理系统:从部署到排坑全攻略

SpringBoot+Vue+MySQL财务管理系统:从部署到排坑全攻略 简介这是一套基于Java、SpringBoot、Vue与MySQL构建的财务管理系统毕业设计资源面向计算机科学与技术、软件工程等专业学生适用于毕业设计、课程设计及期末大作业。系统覆盖账务处理、报表生成、资产管理、预算控制等核心功能前后端代码完整附带数据库脚本与论文文档数据库基于MySQL 5.7以上设计开发环境使用IDEA、Maven和Navicat下载后无需修改即可部署运行。资源共450个文件主要包含123个Java后端逻辑文件、47个Vue前端页面、161个SVG图标资源以及SQL脚本、JS、XML配置、图片和文档等压缩包大小17.66MB结构清晰便于学习。目前已有44人学习使用。对希望快速掌握SpringBoot整合Vue开发流程、理解财务系统业务设计的学生来说这套项目提供了可直接参考的完整方案也适合在此基础上二次拓展。1. 拿到 javaspringbootvuemysql 财务管理系统项目包之后先想清楚三件事别人发来一个「基于javaspringbootvuemysql的财务管理系统 源码数据库论文(高分毕设项目).zip」你解压后最可能的状态是目录挺全但不知道先碰哪个文件。这类项目最常见的翻车点不在业务代码而在三个地方——mysql 版本和驱动不匹配、前端转发端口配错、sql 脚本带着库名导入导致数据落到错误库里。这个项目解决的是一个完整账务闭环凭证录入、科目管理、余额汇总、报表统计和基于角色的权限控制。适合三类人正在选毕设题目的 java 方向学生、想快速搭一套内部财务小工具的开发、准备面试时拿真实项目讲 RBAC 与事务的求职者。下面按「先跑起来、再读代码、再改出亮点、最后排雷」的顺序拆。2. 把整套工程跑通从 zip 到浏览器能打开页面的最小路径2.1 解压后先看目录结构别急着双击启动类高分毕设项目包一般装三类实物源码、数据库脚本、论文文档。源码里常见的是 backend 和 frontend 两个目录backend 是 springboot 的 maven 项目frontend 是 vue 工程sql 目录里放初始化脚本doc 里是论文和答辩 PPT。我不会一上来就点启动类而是先用命令把顶层结构扫一遍find . -maxdepth 2 -type d ls -la backend/pom.xml frontend/package.json sql/看pom.xml是为了确认 springboot 和 mysql 驱动版本看package.json是为了确认 vue 版本和路由方式看sql目录是为了确认数据库脚本是不是独立文件。如果这三样齐全这个包就是完整的如果缺 sql 脚本后面所有配置都无从谈起。先做这三步的原因很现实很多同学打开项目就点运行报错后才发现 mysql 驱动是 5.x 却连了 8.x 的库或者 vue 用的还是 2.x 但代码是 3.x 的写法。版本错位是这类项目第一大坑解压后花五分钟确认技术栈版本能省下后面一整天的排错时间。2.2 数据库初始化用 mysql 命令行导入 sql 脚本的标准动作拿到 sql 脚本之后我一般先在本地 mysql 里建一个独立的库再导入。新建数据库时直接指定字符集避免后面中文乱码mysql -u root -p -e CREATE DATABASE finance DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; mysql -u root -p --default-character-setutf8mb4 finance sql/finance.sql第一条命令的-e表示执行后面的 SQL 语句DEFAULT CHARACTER SET utf8mb4是让表和字段默认继承 utf8mb4 编码第二条命令用把 sql 文件内容重定向到 mysql 客户端--default-character-setutf8mb4保证客户端和服务器通信时用同一种字符集。导入之前一定先看 sql 文件头部有没有CREATE DATABASE和USE语句head -50 sql/finance.sql如果脚本里自带USE finance;而你的库名也叫 finance导入没问题如果脚本里写的是别的库名导入后数据会落到那个库里后端配置的库名就对不上了。验证导入成功的命令很简单mysql -u root -p -e USE finance; SHOW TABLES;看到凭证表、科目表、用户表这些表名说明数据库这一层通了。这里还要提醒一句如果你照着 mysql 5.7.44 的安装教程装好了库后端驱动却用的是 8.0 的包连接阶段就会报错后面 5.2 节会细说。2.3 springboot 后端启动改 application.yml 里的四个配置项后端跑不起来十次里有八次是application.yml里的数据库连接没配对。以下是一份能兼容 mysql 8.x 的标准配置server: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/finance?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/ShanghaiuseSSLfalseallowPublicKeyRetrievaltrue username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver mybatis: mapper-locations: classpath:mapper/*.xmlurl里每一段参数都有用useUnicodetrue和characterEncodingutf8解决中文乱码serverTimezoneAsia/Shanghai不配的话 java 和 mysql 之间会差 8 小时useSSLfalse关掉 ssl 警告allowPublicKeyRetrievaltrue是 mysql 8 连不上时最容易缺的一项。driver-class-name用的是com.mysql.cj.jdbc.Driver对应 mysql 8.x 驱动如果你本地是 5.7可以用com.mysql.jdbc.Driver但更推荐统一换 8.x 驱动。启动命令很简单cd backend mvn spring-boot:run日志里看到Started Application说明启动成功然后访问http://localhost:8080验证。这里要专门说一个版本问题不少同学图新鲜用 springboot 3.x结果老代码里到处都是javax.servlet包名要手动改成jakarta.servlet版本太高反而把自己卡死。做毕设和内部工具springboot 2.7.x 配 mysql 8.x 是最稳妥的组合踩坑最少、网上资料也最多。2.4 vue 前端启动npm 镜像、端口和接口转发配置前端启动分三步装依赖、起服务、转发接口。装依赖时用国内镜像不然 node_modules 下载到一半容易超时cd frontend npm install --registryhttps://registry.npmmirror.com npm run servenpm install装的是package.json里声明的依赖--registry参数临时切换镜像源只在当前命令生效。npm run serve启动 vue 开发服务器默认端口一般是 8080但后端的 springboot 已经占了 8080所以要在vue.config.js里换个端口并配置接口转发module.exports { devServer: { port: 5173, proxy: { /api: { target: http://localhost:8080, changeOrigin: true } } } }port: 5173是前端开发服务器的端口和后端 8080 错开proxy里的/api是匹配规则前端请求只要以/api开头就会被转发到target指向的后端地址。changeOrigin: true必须开否则后端收到请求时拿到的 Host 头是前端的有些拦截器会误判。启动后用浏览器打开http://localhost:5173如果页面能登录、能查数据说明前后端已经打通。再多提一句 vue 路由如果前端用了 vue-router地址栏带#是 hash 模式不带是 history 模式。本地联调用 hash 模式最省事刷新不会 404history 模式刷新会直接打到后端处理方案在第五章第五节。3. 读懂财务系统的核心凭证、科目、余额与权限模型3.1 凭证、科目与余额三张核心表如何联动财务管理系统和普通 CRUD 系统的本质差别在于它不是一个增删改查页面而是一套有约束的账务闭环。每一笔业务产生一张凭证凭证至少要包含两条分录——借方一条、贷方一条——两边的金额必须相等。科目表决定这笔钱记到哪个会计科目余额表则是把凭证分录的金额汇总到科目上。理解这个闭环最好的入口是查凭证是否平衡。以下 SQL 可以用来揪出所有借贷不平的凭证SELECT voucher_id, SUM(debit_amount) AS total_debit, SUM(credit_amount) AS total_credit FROM voucher_entry GROUP BY voucher_id HAVING total_debit total_credit;这个查询把凭证明细按voucher_id分组分别累加借方金额和贷方金额然后用HAVING筛出两边不相等的凭证。GROUP BY在这里负责分组HAVING负责对分组后的结果做条件过滤和WHERE的区别是它可以用聚合函数。余额表联动通常发生在凭证审核通过后UPDATE account_balance SET balance balance 100.00 WHERE account_code 1001;需要注意金额字段用DECIMAL(15,2)不要用float。浮点数的二进制表示会有误差累计几十笔后账就可能差出几分钱对账的时候非常头疼。另一个容易被忽略的点是月份排序报表里如果按月份排序日期字段要用DATE类型且配合ORDER BY MONTH(voucher_date)用字符串排序会出现「10 月排在 9 月前面」这种问题这种细节答辩时老师经常问。3.2 从表结构反推业务流程报销、收款、对账的边界拿到这套源码不要只盯着页面看先顺着表结构把业务流程反推出来。常见财务流程包括报销、收款、付款、转账每个流程都对应一类单据而这类单据表里几乎都有一个state字段0 表示草稿、1 表示已审核、2 表示已入账。审核接口必须做状态校验否则会出现重复审核的脏数据。正确写法是先查当前状态再更新UPDATE voucher SET state 2 WHERE id 123 AND state 1;WHERE条件里带state 1是乐观锁的思路——只有当前状态是「已审核」时才允许改成「已入账」如果影响行数为 0说明状态已经被别人改过要么返回提示要么抛异常让前端重新拉取数据。讲到并发控制面试时如果被问到 mysql 锁的分类可以顺着这个例子展开mysql 里锁的分类有表锁、行锁、间隙锁但毕设场景最实用的是「行锁 乐观锁字段」。比如更新余额时UPDATE account_balance SET balance balance - 100.00, version version 1 WHERE account_code 1001 AND version 5;version是版本号字段每次更新加一。更新前查出version 5更新时把这个值放进WHERE如果期间有别的事务改过这行version已经变了这条更新影响行数为 0就能检测出冲突。这种设计用来保证多人同时审核时不会超扣余额比直接给表加锁更轻量也是论文里值得写一笔的亮点。3.3 权限模型为什么财务系统必须区分录入、审核、查看财务系统三个人群必须有边界录入员只能做单据录入和修改草稿审核员负责审核和入账管理员或领导只看报表和汇总。这个权限模型一般用 RBACuser、role、menu 三张主表加上 user_role、role_menu 两张关联表。后端拦截我建议用 Spring Boot 的拦截器加方法级注解而不是在每个 Controller 里写 if。最小实现是加一个HandlerInterceptorOverride public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(authInterceptor) .addPathPatterns(/**) .excludePathPatterns(/login, /css/**, /js/**, /images/**); }addPathPatterns(/**)表示拦截所有请求excludePathPatterns放行登录接口和静态资源。这里最容易踩的坑是漏放行静态资源导致前端页面加载不出 css 和 js。放行后登录接口和资源文件不会进入拦截逻辑其余请求先走登录校验再做方法级权限判断。方法级权限可以用 AOP 注解实现定义一个RequiresPermission(finance:voucher:audit)注解写一个切面在进入方法前检查当前用户是否拥有对应权限码。这样权限逻辑从 Controller 中剥离出来代码干干净净而且 RBAC 本身就是 java 面试题里高频词把这套表结构讲清楚比背概念有用得多。4. 把它改造成你自己的「高分」项目三个低成本高回报方向4.1 报表加图表给现有数据接上 echarts 的最小改动很多毕设的系统页面只有表格答辩时没视觉冲击。加分最快的做法是给收入统计页加一个折线图改动量很小。后端报表接口可以直接复用返回月份列表和金额列表前端用 echarts 渲染npm install echarts --saveimport * as echarts from echarts; const chartDom document.getElementById(incomeChart); const myChart echarts.init(chartDom); myChart.setOption({ xAxis: { type: category, data: months }, yAxis: { type: value }, series: [{ type: line, data: amounts }] });setOption里的xAxis.data放横轴月份series.data放纵轴金额两个数组的数据源都来自后端同一个接口。series.type改成bar折线图立刻变柱状图论文截图里放两种图显得工作量更足。后端对应 SQL 要注意按月份聚合后的排序SELECT MONTH(voucher_date) AS month, SUM(amount) AS total FROM voucher WHERE voucher_date BETWEEN 2024-01-01 AND 2024-12-31 GROUP BY month ORDER BY month;GROUP BY month里的month是 SELECT 里的别名ORDER BY month也引用这个别名mysql 允许这样写。如果ORDER BY不加month而是直接排日期字符串会遇到前面说的「10 月排在 9 月前」的问题。4.2 加一道审批流状态机从草稿到入账的规范化控制大部分毕设里的状态流转写得很随意前端按钮控制能不能点后端不校验。真正像样的做法是用状态机。先定义枚举public enum VoucherState { DRAFT(0), PENDING(1), APPROVED(2), POSTED(3); }再定义合法迁移路径MapVoucherState, SetVoucherState transitions new HashMap(); transitions.put(VoucherState.DRAFT, Set.of(VoucherState.PENDING)); transitions.put(VoucherState.PENDING, Set.of(VoucherState.APPROVED, VoucherState.DRAFT)); transitions.put(VoucherState.APPROVED, Set.of(VoucherState.POSTED));DRAFT能提交为PENDINGPENDING能审核通过或者退回到草稿APPROVED才能入账为POSTED其他路径一律非法。写一个通用校验方法VoucherState next transitions.get(current).contains(target) ? target : throw new BizException(非法的状态迁移);状态机的价值是让流程边界一目了然。前端表格里操作列可以用 vue 插槽按当前状态渲染不同按钮草稿显示「提交」待审核显示「审核」「退回」已审核显示「入账」。vue 插槽正好是这个场景最自然的扩展点也顺带展示了组件化的功底。4.3 论文怎么组织测试用例表和核心代码的取舍论文别写成代码说明书评委要看到的是你「会设计」不是你会贴代码。常见章节结构是需求分析、总体设计、数据库设计、系统实现、系统测试。数据库设计重点放 ER 图和三张核心表的字段说明系统实现里放核心方法的接口签名 一段关键代码比如凭证审核方法、状态机迁移方法。测试章节是整个论文里最有说服力的部分用表格写测试用例用例编号测试模块操作步骤预期结果实际结果TC-01凭证审核录入借贷相等的凭证并审核凭证状态变为已审核与预期一致TC-02凭证审核录入借贷不平的凭证并提交系统提示借贷不平衡与预期一致TC-03权限控制录入员访问审核接口返回无权限提示与预期一致测试用例表需要覆盖正常流、异常流、权限流三类场景。写论文时还要注意一致性定稿前用SHOW CREATE TABLE voucher;导出建表语句和论文里的 ER 图逐一核对。开发过程中改表结构是常态但论文里图没同步答辩时老师打开数据库一对比一眼就能看出来论文是后补的。另外测试章节里可以专门写一条「月度报表金额必须按时间顺序排列」的用例把排序问题作为已知 bug 修复记录写进去这种真实踩坑记录比泛泛而谈「系统稳定运行」可信得多。5. 避坑指南springboot vue mysql 组合里的高频问题与排查方法5.1 浏览器报 CORS 跨域接口转发没有生效现象前端页面能打开但登录请求发出去后控制台报Access to XMLHttpRequest ... has been blocked by CORS。原因前端开发服务器在 5173 端口后端在 8080 端口浏览器因为同源策略直接拦截了跨端口请求。你配置了vue.config.js的转发但前端请求很可能写成了绝对地址http://localhost:8080/api/login绝对地址会绕过转发直接走后端。解决把前端所有请求路径改成相对路径/api/login、/api/voucher/list让浏览器把请求发到 5173再由 devServer 转发到 8080。排查时先看 network 面板里请求的地址是localhost:5173/api/...说明转发生效了是localhost:8080/api/...说明写死了绝对地址。5.2 mysql 版本与驱动不匹配时区与加密规则导致的连接失败现象springboot 启动时报Communications link failure或者更具体的Public Key Retrieval is not allowed。原因mysql 8.x 默认加密插件是caching_sha2_password旧驱动不认识这种加密方式另外 URL 里没配serverTimezone驱动和服务器时区不一致也会直接失败。解决驱动类换成com.mysql.cj.jdbc.DriverURL 里加三个参数url: jdbc:mysql://localhost:3306/finance?useSSLfalseallowPublicKeyRetrievaltrueserverTimezoneAsia/Shanghai如果你本地装的是 mysql 5.7.44默认加密是mysql_native_password对应的驱动用com.mysql.jdbc.Driver也能跑但 8.x 的驱动向下兼容 5.7统一用 8.x 驱动最省事。实践中发现很多人把本地库和远程库混用本地是 5.7、服务器是 8.0两边的连接参数不一致导致本地正常、部署就崩这个一定要检查清楚。5.3 vue 打包放进 springboot 后刷新页面 404现象前端npm run build之后把dist目录里的文件复制到src/main/resources/static启动后端首页能打开但点击路由再刷新就 404。原因vue-router 用了 history 模式地址栏里是/finance/list这样的真实路径刷新时浏览器直接请求后端这个路径后端没有对应的 Controller返回 404。解决最省事的办法是把路由模式改成 hashconst router new VueRouter({ mode: hash, routes });hash 模式下地址变成/#/finance/list刷新时只会请求/后端能正确返回index.htmlvue-router 再根据 hash 内容解析路由。如果非要保留 history 模式就得在后端加一个兜底转发把非静态资源路径全部转发到index.html但这样要处理静态资源和接口的排除逻辑毕设阶段不划算。这是 vue 打包放进 springboot 中遇到最多的坑按 hash 模式改一行就能解决。5.4 数据库导入乱码中文全是问号现象导入 sql 脚本后前端页面上显示的中文全部是???。原因客户端导入时字符集不是 utf8mb4或者 sql 文件本身是用 gbk 编码保存的。utf8mb4和utf8在 mysql 里是两回事utf8mb4才完整支持中文和 emoji。解决导入时显式指定字符集mysql -u root -p --default-character-setutf8mb4 finance sql/finance.sql如果 sql 文件是 gbk 编码先转成 utf8 再导入iconv -f gbk -t utf8 finance.sql finance_utf8.sql mysql -u root -p --default-character-setutf8mb4 finance finance_utf8.sql此外后端连接串里的characterEncodingutf8也要保留前后端任何一环字符集不一致都可能乱码。怀疑乱码时先用SHOW CREATE TABLE voucher;看表的默认字符集是不是utf8mb4再往前排查文件编码这两个位置基本能覆盖 90% 的乱码原因。5.5 论文里的表名和实际数据库对不上答辩被质疑现象答辩老师现场打开数据库发现表的字段和论文 ER 图里的不一样比如论文里写了user_id数据库里是uid。原因开发过程中改了表结构但论文是后期一次性写完的没有对照实际库更新。解决定稿前做一次一致性检查把所有表的建表语句导出mysqldump -u root -p --no-data finance schema_only.sql然后打开这个文件逐表对照论文里的 ER 图和字段说明表。发现不一致时改论文而不是改数据库——数据库结构已经被代码引用改动代价更大。答辩前还可以把这个文件放进论文附录作为「数据库设计」章节的真实依据反而比空口说更可信。这个习惯我后来一直保留不只是毕设公司里交付文档前我也会做一次 schema 导出核对。6. 用一套「坏数据」把这个财务系统测到露馅三分钟验证方案答辩前最该做的不是再跑一遍正常流程而是故意喂坏数据。我自己常用的验证方案是三类造一张借贷不平的凭证看系统能不能拦下来造一张余额不足的付款单看会不会出现负余额对已经入账的凭证再次审核看状态机能不能挡住。直接在数据库里插一条借贷不平的凭证分录INSERT INTO voucher_entry (voucher_id, account_code, debit_amount, credit_amount) VALUES (999, 1002, 100.00, 200.00);然后调用凭证审核接口。一个合格的财务系统这时必须报「借贷不平衡」如果它照常审核通过说明校验只在前端页面做了后端没兜底这是最典型的扣分点。再用SELECT * FROM account_balance WHERE balance 0;查一遍负余额如果查得到说明付款逻辑里没有余额校验。最后把已入账凭证再点一次审核状态机应当直接拒绝而不是允许重复流转。这个验证方法的妙处在于它能同时暴露三类问题校验缺失、并发控制缺失、状态控制缺失。论文测试章节直接写这三条用例比写二十条正常用例都有说服力。我做类似系统时本地一切正常换了台部署机器后 mysql 版本变成 8.x连接参数不对卡了一下午后来把所有连接参数整理进一个 profile 文件部署时一键切换才收场。也顺便说一句本地开发直接用 mysql 官方安装包比 Docker 更省心避免端口映射和挂载目录权限带来的额外变量。希望这套验证思路帮你在答辩前把系统真正的薄弱点找出来别等到老师动手才翻车。本文还有配套的精品资源点击获取
返回列表