
1. 这个项目到底能做什么功能拆解与技术栈定位1.1 从热搜词看大家真正关心什么拿到这个标题我先扫了一眼相关的网络热词。排在前面的是springboot版本太高java启动失败怎么解决android进度条这类问题后面还跟着一大串关于 Android 文件路径的搜索记录。这说明正在找这个项目的读者大概率不是在选型阶段而是已经拿到源码、准备跑起来结果被环境问题卡住了。这其实非常真实。一个源码文档运行视频讲解视频的毕业设计项目它的完整价值不在于代码本身有多惊艳而在于能不能顺利跑起来、跑起来之后能不能讲清楚每个模块的作用。这篇博文我会按照从拿到源码到最终交付的完整链路来写重点放在那些文档里不会细说、但实际跑项目时一定会撞上的坑。先把这个项目的核心能力讲清楚。这是一个典型的双端个人财务系统前端是 Android 原生客户端后端是 Spring Boot 提供的 RESTful API 服务数据落在 MySQL 里。用户可以在手机上完成注册登录、记一笔收入或者支出、给这笔账打上分类标签餐饮、交通、购物、工资等等、设置月度预算、查看消费统计报表。后端负责处理这些请求通过 Token 机制保证每个用户只能看到自己的账单数据。这类项目的技术栈非常经典Spring Boot 负责接口层和业务逻辑MyBatis Plus 负责数据库操作MySQL 存储数据Android 端用 Retrofit 或者 OkHttp 做网络请求用 MPAndroidChart 画统计图表用 SharedPreferences 或者本地 SQLite 缓存登录状态。整套东西没有特别冷门的技术但正因为经典反而非常适合拿来练手和答辩讲解。1.2 双端架构下的数据流与模块划分想把这个项目吃透第一步要把数据流理清楚。我习惯用一条最简单的用户操作路径来串起整个架构用户在 Android 端输入一笔消费金额点击保存这时候客户端把这笔数据封装成 JSON 格式通过 HTTP 请求发到 Spring Boot 后端后端先校验请求头里的 Token 是否有效然后调用 Service 层的业务方法再通过 MyBatis Plus 的 Mapper 接口把数据写入 MySQL 数据库写入成功后后端返回一个 JSON 响应Android 端收到后刷新界面。从模块划分的角度看后端可以分成四层Controller 层接口暴露层接收 Android 端发来的请求负责参数校验和响应封装。通常分为 AuthController注册登录、BillController账单增删改查、CategoryController分类管理、BudgetController预算设置、StatisticsController统计报表。Service 层业务逻辑层处理具体业务规则。比如新增账单时判断是否超过当月预算、统计报表时按月份和分类聚合数据、注册时检查用户名是否重复。Mapper 层数据访问层MyBatis Plus 的 BaseMapper 接口提供单表 CRUD 方法复杂查询用注解或 XML 写 SQL。Entity 层实体映射层对应数据库表结构的 Java 类用 TableName 和 TableField 注解做字段映射。Android 端的结构一般按 MVC 或者 MVP 来分包Activity 处理界面交互Adapter 负责列表展示网络请求封装在一个单独的工具类或者 Retrofit Service 接口里实体类放在 entity/model 包下。对答辩来说讲清楚这条数据流比讲清楚某个界面长什么样重要得多。评委最常问的问题就是这笔账单从点击按钮到写入数据库经过了哪些环节能把这条链路串下来项目分基本就能拿住一大半。2. 环境配置与版本匹配拿到源码后最容易被卡住的第一关2.1 JDK、Spring Boot 与 Android SDK 三方版本怎么对齐先说结论这个项目里 90% 的java启动失败都和版本不匹配有关。个人财务系统这种毕业设计项目用的技术版本往往比较保守我见过很多同学的开发环境是 JDK 17 Spring Boot 3.x但源码里是 JDK 1.8 Spring Boot 2.x一启动就报错翻日志看到一堆 UnsupportedClassVersionError 或者 BeanCreationException。这里我直接给出最稳的组合方案按这个来基本不会出问题组件推荐版本原因JDK1.88u202 或更高绝大多数国产生成项目基于 JDK 8 编写兼容性最好Spring Boot2.4 ~ 2.7与 JDK 8 完全兼容MyBatis Plus 集成资料最丰富MyBatis Plus3.4.x ~ 3.5.x支持 Spring Boot 2.x自动建表和逻辑删除功能稳定MySQL5.7 或 8.0两个版本都可以注意 8.0 驱动类名不同Android Studio最新稳定版即可Android 端兼容性由 compileSdk 控制Studio 本身不太影响compileSdk / targetSdk31~34 均可注意 targetSdk 大于 30 时需要在清单文件声明分区存储适配为什么强调 JDK 一定要和前端的 compileSdk 分开看因为 Android 构建用的是它自己内置的 JDKAndroid Studio 里可以单独设置 Gradle JDK 版本后端的 JDK 版本和 Android 端的 JDK 版本可以不一样。很多同学以为只装一个 JDK 就够了结果后端跑起来了Android 构建却报 Unsupported class file major version其实就是 Gradle 使用的 JDK 版本太高把 Android Studio 的 Gradle JDK 切到同一个 JDK 8 就解决了。2.2 常见启动失败场景的排查链路如果你照着运行视频做还是启动不了按下面这条链路一步步查不要乱改代码第一步看控制台报错类型。如果是UnsupportedClassFileVersionError说明编译版本高于运行版本检查 IDEA 右下角的 Project Structure 里 Project SDK 和 Modules SDK 是否都指向了 JDK 8。如果是Port already in use说明 8080 被占用了到application.properties或者application.yml里把 server.port 改成 8081、8082 都行。第二步看数据库连接配置。报错里出现com.mysql.cj.jdbc.exceptions.CommunicationsException或者Access denied for user基本就是spring.datasource.url、username、password有问题。注意 MySQL 8.0 的连接 URL 要写成jdbc:mysql://localhost:3306/finance_db?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/Shanghai其中 driver-class-name 要填com.mysql.cj.jdbc.Driver如果你用的是 MySQL 5.7driver-class-name 则是com.mysql.jdbc.Driver。第三步确认数据库是否创建了。Spring Boot 启动时会尝试连接数据库但不会自动帮你在 MySQL 里创建数据库。你需要先手动执行CREATE DATABASE finance_db DEFAULT CHARACTER SET utf8mb4;否则报错信息会直接提示 Unknown database。这里多说一句 maven 的配置。拿到源码后别急着mvn spring-boot:run先检查本地 Maven 的 settings.xml 里有没有配置阿里云镜像。国内网络环境下拉取 Spring Boot 依赖如果不走镜像等十几分钟都是很正常的事。在mirrors节点加一个mirror idalimaven/id mirrorOfcentral/mirrorOf urlhttps://maven.aliyun.com/repository/central/url /mirror能省下大量等待时间。另外源码里如果附带了 mvnwMaven Wrapper优先使用它来构建能避免本机 Maven 版本和项目期望版本不一致的问题。3. 数据库设计与 MyBatis Plus 自动建表从表结构谈起3.1 个人财务系统的核心数据模型个人财务系统的表结构看起来简单但设计时的取舍直接决定后期开发效率。一个能跑的项目和讲起来有逻辑的项目差别就在这里。为了把表和表之间的关系说清楚我自己画过很多遍思路图核心有四张表user用户表user_id 主键、username 唯一索引、password存储加密后的密码、nickname、create_time。这张表是所有业务数据的归属锚点。category分类表category_id 主键、user_id关联所属用户、name、type0 支出 / 1 收入、icon。分类为什么用单独一张表而不是写死在客户端因为用户在设置预算和查看报表时需要按分类聚合统计单独成表才能支持动态新增自定义分类。bill账单表bill_id 主键、user_id、category_id、amount金额、type0 支出 / 1 收入、note备注、bill_date账单日期、create_time。索引建议建在 (user_id, bill_date) 上统计报表按月、按分类查询时非常快。budget预算表budget_id 主键、user_id、category_id可以允许为空表示整体预算、budget_amount、month预算月份格式如 2025-07、create_time。这里预算按月设置一个用户一个月可以有多条分类预算。你可能会发现bill 表其实可以不用冗余一个 type 字段因为通过 category_id 能关联出收支类型。但在个人财务这种小体量项目里冗余 type 字段能省掉大量的连表查询统计报表时哪怕不 join 分类表也能直接按 type 做聚合。多表冗余还是少表关联是解释成本和查询成本的权衡在答辩时把这个讲清楚评委印象会比较好。3.2 MyBatis Plus 根据实体类自动创建表的 SQL 逻辑项目里大概率用到了 MyBatis Plus很多版本还顺手带了自动建表功能。你需要搞清楚它背后的原理——这其实是 MyBatis Plus 的DbType判断加TableInfoHelper解析实体类信息再拼接 DDL 语句的过程。如果项目里没有配置自动建表也可以手动用create table语句建库两者结果一致。如果用 MyBatis Plus 的自动建表核心逻辑是启动时扫描带TableName注解的实体类读取每个类的字段注解TableField和主键注解TableId生成对应的建表语句。你的实体类最好不要用int或Integer作为主键类型推荐Long自增主键配合TableId(type IdType.AUTO)这样建表语句会自动生成auto_increment免去后续手动设自增的麻烦。字段命名上有个坑Java 属性用驼峰命名比如billDate数据表字段用下划线命名bill_dateMyBatis Plus 默认开启驼峰映射所以注释和 SQL 里的字段名统一用下划线避免后面手写 SQL 时对不上。金额字段要用DECIMAL(10,2)而不是DOUBLE原因很简单DOUBLE 是浮点数算钱的时候会出现 0.1 0.2 0.30000000000000004 这种精度问题财务数据必须用定点数。如果你需要手动生成建表 SQL用SHOW CREATE TABLE bill;把这个语句保存下来放进项目的db文件夹里README 里写清楚数据库初始化的步骤这样别人换一台电脑测试不用依赖自动建表也能把库建起来。这属于典型的多一步操作但让别人省很多时间的细节。4. 后端接口设计与鉴权机制让 Android 端安全地读写数据4.1 Token 认证的完整设计个人财务系统不能忽略权限问题——如果没有任何鉴权机制意味着任何一个人查看你的账单接口都能把全库数据拉下来。项目里通常用 Token登录令牌的方式来控制访问。完整流程是这样的用户输入用户名密码点击登录Android 端把账号密码 POST 到/api/auth/login后端校验用户名密码通过后生成一段加密字符串Token并返回到客户端客户端把这个 Token 存在本地的 SharedPreferences 里每次发起业务请求时在请求头里带上Authorization: token字符串后端写一个拦截器或者 Spring Boot 的HandlerInterceptor在请求进入 Controller 前检查 Token 是否存在、是否过期、是否对应该用户。这个设计里有几个容易踩坑的点。第一拦截器的放行路径要写对注册、登录这两个接口要放行其他接口全部拦截。如果拦截器没写好Android 端登录成功后一请求账单列表就返回 401排查过程很容易让人抓狂。第二Token 过期时间的处理Token 一般放一个有效期比如 24 小时超过这个时间就需要重新登录。实现的时候在 Token 里塞一个过期时间戳每次请求校验一下当前时间即可。第三密码不能明文存储。这个项目虽然只是个人财务系统但密码加密存储是安全常识。用BCryptPasswordEncoder或者 MD5 盐值做加密都可以答辩时提一句密码经过哈希存储数据库被脱库也拿不到明文是加分的。4.2 接口返回格式与日期序列化问题Android 端解析 JSON 时最头疼的问题就是日期格式。后端返回的LocalDateTime如果直接用默认序列化会变成一段数组形式[2025, 7, 15, 10, 30, 45]Android 端用 Gson 或者 Fastjson 解析时直接报错。解决办法是在 Spring Boot 的配置里统一指定日期格式spring.jackson.date-formatyyyy-MM-dd HH:mm:ss spring.jackson.time-zoneGMT8注意时区一定要设成 GMT8否则你在深圳记录的账单时间会被 Jackson 按默认时区UTC序列化前端看到的时间比实际时间早 8 个小时。接口返回的统一 JSON 格式也应该固定下来。常见的封装是一个 Result 类包含 code状态码、message提示信息、data业务数据{ code: 200, message: success, data: { billId: 1, amount: 39.90, categoryName: 餐饮 } }Android 端只需要判断code是否等于 200再做对应处理不需要每个接口都单独处理异常分支。这是前后端联调中最基础也是最重要的约定。5. Android 端开发从界面交互到数据同步的实战要点5.1 网络请求封装与敏感数据缓存策略Android 端开发里最影响用户体验的就是网络请求的响应速度和进度反馈。热搜词里出现了android进度条说明很多人在登录、加载账单列表中遇到过界面卡住没有任何提示的情况。我在实战中的做法是写一个HttpUtils工具类封装 Retrofit OkHttp 的核心配置统一设置超时时间连接超时 10 秒、读取超时 15 秒统一添加 Token 请求头拦截器。这样每次发起请求时不必重复粘贴代码而且以后想给所有请求加日志、加公共 header只需要改一处。具体来说在 OkHttp 的拦截器里做 Token 注入OkHttpClient client new OkHttpClient.Builder() .connectTimeout(10, TimeUnit.SECONDS) .readTimeout(15, TimeUnit.SECONDS) .addInterceptor(new Interceptor() { Override public Response intercept(Chain chain) throws IOException { Request original chain.request(); String token SharedPreferencesUtil.getToken(); Request request original.newBuilder() .header(Authorization, token) .method(original.method(), original.body()) .build(); return chain.proceed(request); } }) .build();SharedPreferences 不能存敏感的用户数据比如密码、Token 这种。实际的个人财务项目里Token 存在 SharedPreferences 风险较大尤其是 Android 的/data/data/package_name/shared_prefs/目录在 root 后可被直接读取。常规做法是加密后存或者存入系统保护的存储区域这个复杂度对这个毕设项目来说略高但至少要把Token 不通过明文持久化这个意识写出来比如把 Token 加密后再存密钥放在 JNI 层或者加密的 EncryptedSharedPreferences 里哪怕实际用不到答辩时说出来也会给自己加分。5.2 账单列表、进度条与统计图表Android 的界面部分通常情况下项目会涉及这三个重点账单列表用 RecyclerView 来展示Adapter 绑定数据和点击事件。这里要注意删除账单的交互逻辑个人财务数据的删除是敏感操作最好做二次确认弹一个 AlertDialog 或者 BottomSheet 让用户确认不要点一下就直接删。进度条分为两种一种是页面加载数据时显示在界面中央的转圈菊花ProgressBar数据到达后隐藏另一种是预算使用情况的 HorizontalProgressBar。预算进度条很有意思它直观地告诉用户这个月吃饭的预算已经用了 78%。实现时注意进度条的最大值不能直接设成 100要设成当月预算总额然后用已消费金额作为当前值再做个颜色区分剩余 30% 以下变红色这个体验细节很加分。统计图表一般用 MPAndroidChart。月度支出饼图返回的数据结构常见的是ListPieEntry每一项包含分类名和金额后端统计接口按月返回聚合结果。这里有个细节饼图百分比会自动计算但要注意总额为 0 时的除零问题后端聚合时先用条件查询过滤掉金额为 0 的分类或者前端拿到空列表时显示暂无数据而不是渲染一个空的饼图。5.3 Android 文件路径与系统访问的适配问题热搜词里密密麻麻的/storage/emulated/0/Android/data/...路径说明很多人卡在了 Android 存储权限上。这里需要强调Android 11API 30之后引入了分区存储机制应用不再能随意访问Android/data目录下的其他应用文件直接写死这些路径去读取大概率会触发SecurityException。个人财务系统如果要导出账本数据比如导出 CSV 到本地正确做法是使用MediaStore或者应用专属目录。用getExternalFilesDir(null)得到的是Android/data/你的包名/files路径不需要额外权限这是最简单的方式。如果需要把文件放到公共目录比如 Download则需要申请WRITE_EXTERNAL_STORAGE权限而且 Android 10 以上还要配合requestLegacyExternalStorage或者在分区存储模式下走 MediaStore API。这条虽然和核心记账功能没直接关系但我强烈建议你把这个逻辑理顺。因为这个点的答案非常实战答辩时如果被问到文件导出怎么做的为什么这么写解释清楚会有很明显的差异化效果。6. 项目交付与二次开发从能跑到讲得清的关键一步6.1 运行视频、讲解视频里应该录什么项目标题写明了带运行视频讲解视频这两个视频的内容质量基本决定了买家的使用体验。我自己帮好几个同学录过这类视频总结出一套固定的录制结构运行视频从启动 MySQL 和 Redis如果有用到、执行建库 SQL 脚本开始到启动后端 Spring Boot 项目再到打开 Android 模拟器或真机运行 APP。全程录屏关键操作放慢速度比如数据库密码输入、项目启动等待过程这些地方新手最容易被绕晕。讲解视频按模块讲先讲后端登录注册接口、账单 CRUD、预算逻辑、统计接口再讲 Android 端页面结构、网络层、数据绑定最后串一条完整链路演示。讲解时不要照着源码念要把为什么这么设计讲出来——为什么账单和分类要分开两张表为什么用了 MyBatis Plus为什么 Token 要放在请求头这些是答辩时评委真正会问的东西。6.2 代码打包、文档完善与答辩前的自测清单如果你想把项目作为毕业设计提交或者打算自己跑通后二次开发这几件事一定要在交付前做完项目文档要补齐的内容环境要求JDK 版本、MySQL 版本、Android Studio 版本快速启动步骤数据库初始化、后端启动、Android 端构建运行核心接口说明表格请求方式、路径、参数、返回示例数据库表结构说明每张表的字段含义常见问题 FAQ密码错误、端口被占用、依赖下载失败答辩前的自测清单数据库从零初始化能否跑起来找一台没装过 MySQL 的电脑试试。后端离线启动会不会卡在自动建表确认建表 SQL 脚本存在且可重复执行。Android 端在模拟器和真机上分别测一次确认模拟器网络地址10.0.2.2 访问本机后端和真机用局域网 IP的差异。Token 过期后重新登录是否正常同一账号在不同设备登录会不会互相顶掉如果项目没有做单点登录这个可以留在文档里作为已知不足。这里再提醒一句换一台电脑跑不起来的项目根本原因九成出在环境上。所以交付时把环境依赖说清楚比任何代码优化都重要。我自己习惯的做法是把 JDK 8 的安装包路径、MySQL 的初始化脚本、Maven 镜像配置全都写进一个环境准备.md新电脑照着做十五分钟就能跑起来这比讲解视频更省事。6.3 个人财务系统进阶方向如何在这个基础上多走一步项目交付不等于终点。很多拿到这套源码的人其实有更多需求——或者想把这个项目作为跳板做出更有竞争力的作品。几个性价比很高的扩展方向加入图表对比功能月度支出和收入趋势折线图以及环比、同比数据。SQL 上用DATE_FORMAT(bill_date, %Y-%m)分组再聚合即可Android 端加一个折线图页面。加入定时提醒比如每月可以生成一次月度账单总结消息——不过这不涉及短信通知只保留待办提醒或本地通知即可用 WorkManager 配合 Android 系统通知就能实现。加入多端数据同步把 Android 端的数据改为优先读取本地 SQLite 缓存网络不好时先记账联网后再和后端同步。这个功能很接地气实现起来也不难数据库层面加一个 sync_status 字段就行。引入报表导出用 POI 或 EasyExcel 生成 Excel 报表文件后端提供一个/api/export/excel接口Android 端点击按钮下载并打开。个人觉得这个功能最实用也最能体现工程能力。这些扩展方向都跑不掉最基础的 永远保持后端接口的兼容性 这一条新增接口时不要改掉旧的返回格式否则老版本 Android 端会直接崩溃。越是小的项目接口协议的稳定性越重要。写在最后跑通之后记得把为什么也讲清楚这套 Java Spring Boot Android 的个人财务系统从技术难度上看不算高但它是典型麻雀虽小、五脏俱全的项目。你在跑通它之后我强烈建议花一个下午做一件事给项目的核心代码加上你自己的注释比如// 校验 Token 是否过期过期则返回 401 让客户端重新登录、// 聚合当前月份每个分类的总支出返回给图表。加注释的过程就是你理解代码的过程答辩时你不需要背源码而是讲出这句代码为什么这么写就够了。我遇到过不少同学拿到源码当天就能跑起来但是被评委追问两句就问懵了。靠的是背稿子。真正稳妥的方式是把数据流、表关系、Token 机制、日期序列化这四件事用自己的话讲一遍讲得顺了这个项目才真正变成你自己的。最后再分享一个小技巧如果你用的是 IntelliJ IDEA跑后端项目之前先按CtrlAltS打开 Settings把 Maven 的自动导入打开再把File - Project Structure里的 Project SDK 确认成 JDK 1.8。我之前愣是卡在这里近一个小时检查了无数次代码最后发现只是这边没对齐。别问我为什么知道这么多坑问就是都踩过。