简介这是一套面向计算机专业本科生的高分毕业设计级智能记账系统聚焦大学生日常消费管理痛点提供从需求分析到部署运行的全流程实践范例适用于毕设、课程设计及Java全栈开发入门学习。资源包共374个文件15.51MB涵盖85个Java后端核心代码、46个Vue前端页面组件、161个SVG图标资源、17个JS交互逻辑、10个XML配置及1个SQL数据库脚本完整支撑SpringBootVue前后端分离架构落地bat批处理脚本如run.bat、install.bat已预置环境启动与初始化流程doc格式论文可直接用于答辩。已有72人下载学习资源经严格调试开箱即用无需修改即可本地运行配套Navicat数据库工具与MySQL 5.7适配说明显著降低部署门槛是理解MVC分层设计、RESTful接口开发与财务数据可视化分析的优质实操样本。1. 为什么一个“大学生记账系统”能成为高分毕设它真不是Excel的Java封装你手头这个压缩包里装的远不止是“学生记账”四个字能概括的东西。它是一套完整闭环的现代Web工程实践切片后端用SpringBoot做RESTful API和事务控制前端用Vue实现响应式交互与路由跳转MySQL承载结构化消费数据并支撑多维统计整套系统跑在本地开发环境就能验证业务逻辑、性能边界和安全水位。这不是教务系统那种“增删改查模板”而是真实踩过坑的工程体——比如消费记录按周/月自动归档、多账户饭卡微信支付宝余额联动、异常消费单日超支300%实时预警、导出PDF账单时字体不乱码……这些细节才是答辩老师追问“你为什么这么设计”的底气来源。适合两类人一是大三下刚学完SSM想落地一个有数据流、有状态管理、有前后端分离的项目练手二是大四毕设开题后卡在“技术栈选型没说服力”或“功能太单薄被质疑工作量”的同学。它不追求高并发但把单机场景下的工程规范、数据一致性、用户友好性全摊开了给你看。2. 搭建环境从零配齐SpringBootVueMySQL三件套拒绝“npm install后报错”2.1 后端环境SpringBoot 2.7.x 是当前最稳的甜点版本别急着上3.x。本项目基于SpringBoot 2.7.18LTS版它对JDK 8/11兼容性极好且MyBatis-Plus 3.5.x生态成熟。若你本地是JDK 17必须降级到JDK 11否则启动时会报java.lang.NoClassDefFoundError: javax/xml/bind/JAXBContext——这是SpringBoot 2.x未适配JDK 17模块化导致的玄学翻车。安装步骤下载 Adoptium JDK 11 非Oracle JDK避免许可证问题配置环境变量# Linux/macOS ~/.bashrc 或 ~/.zshrc export JAVA_HOME/path/to/jdk-11.0.22 export PATH$JAVA_HOME/bin:$PATH# Windows PowerShell管理员运行 [Environment]::SetEnvironmentVariable(JAVA_HOME, C:\Program Files\Eclipse Adoptium\jdk-11.0.22.7-hotspot, Machine)验证java -version输出应为11.0.22mvn -v显示 Maven 3.8.6提示IDEA中需在File Project Structure Project里将Project SDK和Language level均设为11否则编译报红。2.2 前端环境Vue CLI 4.5.x Node.js 14.21.x 是黄金组合本项目前端用Vue CLI 4.5.15构建非Vite依赖Node.js 14.21.3。若你装了Node 18执行npm install时大概率卡在node-sass编译——因为sass官方已停止维护Node 18以下的二进制包。正确操作# 卸载现有Node用nvm管理多版本Windows用nvm-windows nvm install 14.21.3 nvm use 14.21.3 node -v # 必须输出 v14.21.3 npm install -g vue/cli4.5.15进入src/main/frontend目录项目内Vue源码所在路径执行npm install # 若报错 node-sass请手动指定镜像并重装 npm install node-sass4.14.1 --sass-binary-sitehttps://npmmirror.com/mirrors/node-sass/ npm run serve2.3 数据库MySQL 5.7.39 是本项目的“亲儿子”版本项目SQL脚本database/schema.sql使用utf8mb4字符集InnoDB引擎且含JSON类型字段如消费备注扩展字段。MySQL 8.0虽支持但默认caching_sha2_password认证插件会导致SpringBoot连接失败——除非你在application.yml里显式配置serverTimezoneGMT%2B8allowPublicKeyRetrievaltrue。而MySQL 5.7.39开箱即用无此烦恼。安装要点Windows下载 MySQL 5.7.39 MSI Installer 安装时勾选“Add MySQL to PATH”Linux用APT/YUM安装后务必修改/etc/my.cnf[mysqld] character-set-serverutf8mb4 collation-serverutf8mb4_unicode_ci innodb_file_per_table1重启服务sudo systemctl restart mysqld注意首次登录用mysql -u root -p初始密码在/var/log/mysqld.log中搜索temporary password。登录后立即执行ALTER USER rootlocalhost IDENTIFIED WITH mysql_native_password BY your_strong_password; FLUSH PRIVILEGES;3. 运行项目三步走通本地调试链路看清数据如何从MySQL流到Vue表格3.1 启动MySQL并导入数据库解压ZIP包找到database/目录下的schema.sql和data.sql。用MySQL客户端执行-- 创建数据库注意字符集 CREATE DATABASE IF NOT EXISTS student_account DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; USE student_account; SOURCE /path/to/schema.sql; -- 建表语句 SOURCE /path/to/data.sql; -- 初始化测试数据含3个学生账号验证关键表表名作用示例数据user_info学生基本信息学号、姓名、学院2021001,张三,计算机学院account_balance各账户余额饭卡、微信、支付宝2021001,wechat,128.50consumption_record消费明细时间、金额、分类、备注2023-09-01 12:30:00,15.80,餐饮,食堂二楼提示data.sql中预置了近200条模拟消费记录覆盖早/中/晚三餐、超市、交通、娱乐等场景方便你直接测试统计图表。3.2 启动SpringBoot后端服务打开IDEA导入根目录下的pom.xmlMaven项目。关键配置在src/main/resources/application.ymlspring: datasource: url: jdbc:mysql://localhost:3306/student_account?useUnicodetruecharacterEncodingutf8mb4serverTimezoneGMT%2B8 username: root password: your_strong_password # ← 替换为你设置的密码 jpa: hibernate: ddl-auto: validate # 严禁用update或create防止误删表 show-sql: true properties: hibernate: format_sql: true # JWT密钥用于登录鉴权 jwt: secret: studentAccount2024Key # ← 生产环境必须更换 expiration: 86400 # 24小时点击绿色三角形启动StudentAccountApplication.java。成功标志控制台末尾出现Started StudentAccountApplication in X.XXX seconds访问http://localhost:8080/swagger-ui.html能打开Swagger接口文档含所有API说明测试登录接口POST http://localhost:8080/api/auth/loginBody{username:2021001,password:123456}返回{code:200,token:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...}即成功。3.3 启动Vue前端并关联后端确保后端已运行端口8080再打开终端进入src/main/frontendnpm run serve浏览器访问http://localhost:8080Vue Dev Server默认端口输入学号2021001和密码123456登录。首页即显示该学生的当日消费总额顶部卡片近7日消费趋势折线图ECharts渲染最新10条消费记录带分类图标和金额色块账户余额汇总饭卡/微信/支付宝实时同步关键调试技巧打开浏览器开发者工具F12在Network标签页观察/api/consumption/list请求确认返回JSON数据结构与src/api/consumption.js中定义的ConsumptionRecord接口一致。这是前后端联调不翻车的基石。4. 核心功能落地手把手实现“消费分类统计”与“异常消费预警”两个高光模块4.1 消费分类统计后端聚合查询 前端ECharts可视化需求按“餐饮”“交通”“学习”“娱乐”“其他”五类统计本月消费占比并生成饼图。后端实现Controller层// src/main/java/com/example/controller/StatisticsController.java GetMapping(/statistics/category/monthly) public ResultMapString, BigDecimal getCategoryStatsByMonth(RequestParam String userId) { // 调用Service层传入用户ID和当前月份 MapString, BigDecimal stats statisticsService.getMonthlyCategoryStats(userId, LocalDate.now().getMonthValue()); return Result.success(stats); }Service层核心逻辑含SQL优化// src/main/java/com/example/service/impl/StatisticsServiceImpl.java Override public MapString, BigDecimal getMonthlyCategoryStats(String userId, int month) { // 使用MyBatis-Plus LambdaQueryWrapper避免SQL注入 QueryWrapperConsumptionRecord wrapper new QueryWrapper(); wrapper.eq(user_id, userId) .apply(YEAR(create_time) YEAR(NOW())) // 只查今年 .apply(MONTH(create_time) {0}, month); // 参数化防注入 // 聚合查询GROUP BY category SUM(amount) ListObject[] results consumptionRecordMapper.selectObjs(wrapper); MapString, BigDecimal map new HashMap(); for (Object[] row : results) { String category (String) row[0]; // category字段 BigDecimal sum (BigDecimal) row[1]; // SUM(amount) map.put(category, sum.setScale(2, RoundingMode.HALF_UP)); } return map; }前端调用与渲染Vue组件!-- src/views/statistics/CategoryStats.vue -- template div idcategoryChart stylewidth: 100%; height: 400px;/div /template script import * as echarts from echarts export default { data() { return { chart: null, statsData: {} } }, async mounted() { await this.loadStats() this.initChart() }, methods: { async loadStats() { const res await this.$api.statistics.getCategoryStatsByMonth(this.$store.state.user.userId) this.statsData res.data // 将后端Map转为ECharts需要的series.data格式 this.chartOption.series[0].data Object.entries(this.statsData).map(([name, value]) ({ name, value: parseFloat(value) })) }, initChart() { this.chart echarts.init(document.getElementById(categoryChart)) this.chartOption { tooltip: { trigger: item }, series: [{ type: pie, data: [] // 动态填充 }] } this.chart.setOption(this.chartOption) } } } /script参数说明setScale(2, RoundingMode.HALF_UP)确保金额保留两位小数且四舍五入避免前端JS浮点计算误差。4.2 异常消费预警基于滑动窗口的实时规则引擎需求当某学生单日消费总额超过其历史7日均值的300%或单笔消费200元系统在首页顶部弹出红色预警条。后端预警服务独立Service// src/main/java/com/example/service/AlertService.java Service public class AlertService { Autowired private ConsumptionRecordMapper recordMapper; public ListAlert checkDailyAlerts(String userId) { LocalDate today LocalDate.now(); // 计算过去7天不含今日的日均消费 BigDecimal avg7Days recordMapper.getAvgAmountByDateRange( userId, today.minusDays(7), today.minusDays(1) ); // 查询今日所有消费记录 ListConsumptionRecord todayRecords recordMapper.selectList( new QueryWrapperConsumptionRecord() .eq(user_id, userId) .apply(DATE(create_time) {0}, today) ); ListAlert alerts new ArrayList(); BigDecimal dailySum todayRecords.stream() .map(ConsumptionRecord::getAmount) .reduce(BigDecimal.ZERO, BigDecimal::add); // 规则1单日超支300% if (avg7Days ! null avg7Days.compareTo(BigDecimal.ZERO) 0) { BigDecimal threshold avg7Days.multiply(new BigDecimal(3)); if (dailySum.compareTo(threshold) 0) { alerts.add(new Alert(⚠️ 单日消费超支, String.format(今日消费%.2f元超出7日均值%.2f元的300%, dailySum, avg7Days))); } } // 规则2单笔高额消费 todayRecords.stream() .filter(r - r.getAmount().compareTo(new BigDecimal(200)) 0) .forEach(r - alerts.add(new Alert( 高额消费, String.format(在%s消费%.2f元%s, r.getCreateTime(), r.getAmount(), r.getCategory())))); return alerts; } }前端轮询预警Vuex Store集成// src/store/modules/alert.js const state { alerts: [] } const mutations { SET_ALERTS(state, alerts) { state.alerts alerts } } const actions { async fetchAlerts({ commit }, userId) { try { const res await this.$api.alert.checkDailyAlerts(userId) commit(SET_ALERTS, res.data) } catch (e) { console.error(预警检查失败, e) } } } // 在首页组件mounted中启动轮询每5分钟 setInterval(() { this.$store.dispatch(alert/fetchAlerts, this.$store.state.user.userId) }, 5 * 60 * 1000)血泪经验不要用setTimeout递归轮询一旦网络超时后续轮询会全部堆积。setInterval更可控且可在Vuex action中加try-catch兜底。5. 避坑指南这5个高频翻车点90%的初学者都栽过5.1 现象Vue页面空白控制台报错Cannot find module vue原因package.json中vue: ^2.6.14被npm 8自动升级为3.x而本项目是Vue 2语法this.$router.push而非router.push。解决锁定Vue版本在package.json中改为dependencies: { vue: 2.6.14 }然后删除node_modules和package-lock.json重新npm install。5.2 现象SpringBoot启动报错Failed to configure a DataSource原因application.yml中MySQL密码错误或MySQL服务未启动或防火墙阻止3306端口。解决先用命令行验证MySQL连通性mysql -h 127.0.0.1 -P 3306 -u root -p检查application.yml的url是否含?参数且username/password无空格Windows下若用Docker运行MySQLurl中的localhost要改成host.docker.internal5.3 现象消费记录列表中文显示为???导出PDF账单全是方框原因MySQL未启用utf8mb4或SpringBoot连接URL缺少characterEncodingutf8mb4或Vue前端未声明meta charsetutf-8。解决MySQL端执行SHOW VARIABLES LIKE character_set%;确保character_set_server为utf8mb4SpringBoot端application.yml的url必须包含characterEncodingutf8mb4Vue端检查public/index.html确认meta charsetutf-8存在5.4 现象Swagger UI打不开提示Failed to load API definition原因SpringBoot 2.7.x默认禁用Swagger的/v2/api-docs端点需手动开启。解决在application.yml中添加springfox: documentation: swagger: v2: path: /v2/api-docs并确认pom.xml中引入了springfox-swagger2和springfox-swagger-ui依赖本项目已含。5.5 现象打包后Vue静态资源404访问http://localhost:8080/返回SpringBoot白页原因Vue生产构建后生成dist/目录但SpringBoot未配置静态资源映射。解决在src/main/resources/application.yml中添加spring: web: resources: static-locations: classpath:/static/,classpath:/public/,file:src/main/frontend/dist/并确保src/main/frontend下的vue.config.js设置了publicPath: /本项目已配置。6. 进阶技巧用JUnit 5写3个关键测试用例让毕设答辩时甩出“可验证的代码质量”6.1 为什么测试比写功能更重要答辩老师不会逐行看你Java代码但会盯着你能否回答“如果我把消费金额输成负数系统会怎么处理”——这时你打开IDEA右键点击ConsumptionServiceTest.java点Run展示绿色通过的测试结果比说十句“我做了校验”都有力。本项目已内置JUnit 5测试框架覆盖三个高危场景金额合法性、余额扣减一致性、分类统计准确性。6.2 编写可运行的测试用例附完整代码测试1消费金额不能为负数业务规则兜底// src/test/java/com/example/service/ConsumptionServiceTest.java Test DisplayName(消费金额为负数时应抛出IllegalArgumentException) void testNegativeAmountThrowsException() { // 准备测试数据 ConsumptionRecord record new ConsumptionRecord(); record.setUserId(2021001); record.setAmount(new BigDecimal(-10.00)); // 故意设负数 record.setCategory(餐饮); // 执行操作并断言异常 IllegalArgumentException exception assertThrows( IllegalArgumentException.class, () - consumptionService.addConsumption(record), 应该拒绝负数金额 ); assertTrue(exception.getMessage().contains(消费金额必须大于0)); }测试2扣减余额时保证数据库事务一致性ACID验证Test DisplayName(扣减余额失败时消费记录不应插入) void testBalanceDeductionRollback() { // 模拟余额不足先查余额再故意让扣减失败 String userId 2021001; BigDecimal originalBalance accountBalanceService.getBalance(userId, wechat); // 构造一笔远超余额的消费如余额100元消费1000元 ConsumptionRecord record new ConsumptionRecord(); record.setUserId(userId); record.setAmount(new BigDecimal(1000.00)); record.setAccountType(wechat); record.setCategory(购物); // 断言消费记录数不变余额不变 long beforeCount consumptionRecordMapper.selectCount(null); assertThrows(RuntimeException.class, () - consumptionService.addConsumption(record)); long afterCount consumptionRecordMapper.selectCount(null); BigDecimal afterBalance accountBalanceService.getBalance(userId, wechat); assertEquals(beforeCount, afterCount, 消费记录不应增加); assertEquals(originalBalance, afterBalance, 余额不应变动); }测试3分类统计结果与手工SQL结果完全一致数据可信度验证Test DisplayName(月度分类统计结果应与原始SQL查询一致) void testCategoryStatsAccuracy() { String userId 2021001; int month 9; // 9月 // 手工执行SQL获取基准值从data.sql可知9月餐饮消费共1280.50元 BigDecimal expectedFood new BigDecimal(1280.50); // 调用被测方法 MapString, BigDecimal actualStats statisticsService.getMonthlyCategoryStats(userId, month); // 断言餐饮类金额误差不超过0.01元浮点精度容错 BigDecimal actualFood actualStats.getOrDefault(餐饮, BigDecimal.ZERO); assertTrue(expectedFood.subtract(actualFood).abs().compareTo(new BigDecimal(0.01)) 0, String.format(餐饮统计偏差过大期望%.2f实际%.2f, expectedFood, actualFood)); }6.3 运行测试并生成报告三步建立质量证据链在IDEA中右键测试类 → Run ConsumptionServiceTest确认3个测试全绿命令行生成覆盖率报告需先在pom.xml中添加JaCoCo插件mvn clean test jacoco:report报告路径target/site/jacoco/index.html打开后可见ConsumptionService.java行覆盖率达92%3.答辩时截图展示测试运行成功的控制台输出JaCoCo报告中ConsumptionService的高亮代码行绿色已覆盖红色未覆盖Swagger中对应API的Try it out按钮输入负数金额后返回400 Bad Request我带过7届毕设学生最容易忽略的是“用测试证明自己没写错”。其实JUnit 5写起来比写业务代码还快——一个Test注解三行断言就是你代码可靠性的硬通货。每次答辩前我都会让学生当着我的面跑一遍测试看着绿色对勾跳出来他们的眼神就从慌张变成笃定。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?