1. 项目背景与核心价值
去年帮学弟调试他的SpringBoot记账系统时,我意识到这类项目之所以成为经久不衰的毕业设计选题,关键在于它完美融合了技术实践与生活场景。一个合格的记账系统不仅需要处理并发记账、多维统计这些技术难点,更要解决用户"记不住、懒得记、看不懂"的三大痛点。
这个基于SpringBoot的个人记账系统,采用主流技术栈实现收支记录、分类管理、数据可视化等核心功能。相比市面现成应用,毕业设计的独特价值在于:你能自主控制数据存储位置(再也不用担心商业应用突然下架),自由扩展分析维度(比如结合你的消费习惯定制报表),最重要的是——整个过程会逼着你把SpringBoot、MyBatis这些框架技术真正吃透。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术架构设计解析
2.1 整体技术选型
采用经典的SpringBoot + MyBatis Plus组合,这套方案在2023年仍是中小型项目的最优解:
- SpringBoot 2.7.x(LTS版本)
- MySQL 8.0(窗口函数便于统计分析)
- Lombok(减少样板代码)
- ECharts 5.3(可视化方案)
- Vue2 + ElementUI(管理后台选型)
避坑提示:新手常犯的错误是盲目追求最新版本。实测SpringBoot 3.x需要JDK17支持,但学校机房可能仍配置JDK8环境,会导致答辩演示事故。
2.2 分层架构设计
java复制com.example.accounting
├── config # 安全配置/数据源配置
├── controller # 前后端交互入口
├── service # 核心业务逻辑
│ ├── impl # 接口实现类
├── mapper # MyBatis映射文件
├── entity # 数据库实体
├── dto # 数据传输对象
└── util # 工具类包
这种结构虽然传统但足够清晰,特别适合毕业设计答辩时展示你的代码组织能力。我建议额外添加aspect包存放自定义注解,比如用@CostTime记录方法执行耗时,这个小细节能让答辩老师看到你对AOP的实际理解。
3. 核心功能实现细节
3.1 智能记账流程实现
记账系统的核心在于如何降低用户输入成本。我们采用三级分类体系+自动记忆策略:
java复制// 记账时的分类记忆逻辑
public Record addRecord(Record record) {
// 记录用户最近使用的二级分类
String cacheKey = "user:" + userId + ":last_category";
redisTemplate.opsForValue().set(cacheKey, record.getCategoryId());
// 自动填充常用备注(如"早餐"对应"公司楼下包子铺")
if(StringUtils.isEmpty(record.getRemark())){
record.setRemark(categoryService.getDefaultRemark(record.getCategoryId()));
}
return recordMapper.insert(record);
}
配套的前端交互优化:
- 扫码付款后自动跳转记账页(需Android配合)
- 语音输入转文字分类(调用讯飞API)
- 微信账单导入解析(正则表达式匹配金额)
3.2 统计分析模块难点
多维统计报表是答辩加分项,但也是性能重灾区。推荐采用预聚合方案:
sql复制-- 每日消费汇总表
CREATE TABLE stats_daily (
id BIGINT PRIMARY KEY,
user_id INT NOT NULL,
date DATE NOT NULL,
total_amount DECIMAL(12,2),
food_amount DECIMAL(12,2),
traffic_amount DECIMAL(12,2),
UNIQUE KEY idx_user_date (user_id, date)
);
-- 使用定时任务每日凌晨计算
@Scheduled(cron = "0 0 3 * * ?")
public void calculateDailyStats() {
// 使用MyBatis的批量插入
statsMapper.batchInsert(statsList);
}
这样在查询月度报表时,只需简单SUM操作而非扫描原始记录表。实测数据量超10万条时,查询速度从3.2秒降至0.15秒。
4. 典型问题排查实录
4.1 日期区间查询失效
现象:前端传"2023-07-01~2023-07-31",但SQL查询结果包含8月数据
根因分析:
java复制// 错误做法:直接split后new Date()
String[] dates = dateRange.split("~");
Date start = new Date(dates[0]); // 时区问题导致实际是07-01 08:00:00
Date end = new Date(dates[1]); // 变成08-01 08:00:00
// 正确方案:使用LocalDate处理
LocalDate start = LocalDate.parse(dates[0]);
LocalDate end = LocalDate.parse(dates[1]);
return recordMapper.selectBetween(
start.atStartOfDay(),
end.plusDays(1).atStartOfDay());
4.2 饼图数据失真
常见投诉:"我的餐饮消费占比显示120%!"
问题定位:
- 检查是否漏了
GROUP BY user_id导致多用户数据混合 - 确认金额字段是否为DECIMAL类型(浮点数会导致精度丢失)
- 前端ECharts配置检查:
javascript复制series: [{
type: 'pie',
avoidLabelOverlap: false,
itemStyle: {
borderColor: '#fff',
borderWidth: 1
},
// 必须设置normalize属性
normalize: true
}]
5. 答辩专项优化建议
5.1 演示数据准备
不要用系统默认的测试数据!建议准备两套数据:
- 真实场景数据:按你本人过去3个月的真实消费记录导入(去除敏感信息)
- 异常检测数据:包含以下特殊情况:
- 单笔收入50万元(测试大额显示)
- 0.01元的消费记录(测试边界值)
- 跨年度的数据(测试年度报表)
5.2 性能对比展示
在答辩PPT中加入直观对比:
- 原始方案:10000条记录统计耗时
- 优化方案:添加索引后的耗时
- 终极方案:预聚合报表的查询速度
用柱状图展示从3.2s到0.15s的优化过程,这能充分体现你的工程能力。
5.3 扩展性问题
提前准备几个技术深挖点:
- 如果用户量突然增长10倍,系统哪里会先崩溃?(引导到Redis缓存设计)
- 如何保证账单数据不丢失?(引出数据库备份方案)
- 为什么选择ECharts而不是D3.js?(技术选型权衡思考)
最后分享一个血泪教训:永远在演示前做完整流程测试。我曾见过同学在答辩现场发现微信支付回调地址配置的是localhost,导致无法完成支付闭环演示。建议使用内网穿透工具提前部署到云服务器,确保全流程可验证。
