ARTICLE DETAIL

资讯详情

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

SpringBoot+Android个人财务系统全栈实战:从前后端联调到部署避坑指南

SpringBoot+Android个人财务系统全栈实战:从前后端联调到部署避坑指南 从我一踩一个坑的经历说起吧前几年我自己动手串一个完整的全栈项目时最大的感受是——Java SpringBoot 后端和 Android 前端分开学其实都不难难的是把它们真正拧在一起。数据库设计、接口约定、Token 处理、真机联调、图表渲染每一个环节都能让项目卡住好几天。所以当我看到Java springboot基于Android的个人财务系统源码文档运行视频讲解视频这类项目时第一反应不是这有什么难的而是这确实是一个覆盖面非常全、非常适合拿来练手或改造的选题。个人财务系统这个方向我愿称之为毕设与自学历练的黄金切口业务逻辑足够典型涉及增删改查、统计聚合、权限校验、移动端交互但又不会复杂到让人望而却步。它不像电商系统那样有一堆订单状态机、支付回调要处理也不像社交App那样要操心实时通信但它在“前后端如何协作”这件事上把你该踩的坑几乎都覆盖了。这篇内容我会从需求拆解、后端设计、Android 端实现、部署联调、学习路径五个维度展开全程用我实际做项目时的手法来讲不只是摆结论更多是还原当时为什么这么想、真机上跑不通又是怎么排查的。如果你正在准备毕业设计或者想用一个完整项目打通 SpringBoot Android 的技术栈这篇文章能帮你省掉不少自己摸索的时间。1. 项目到底做了什么需求拆解与技术选型的逻辑很多人拿到一个项目源码第一件事就是打开 IDE 跑代码结果跑起来以后一头雾水改两行就崩。我的习惯是先想清楚这个系统到底要解决什么问题给谁用想清楚这三件事后面写代码才不会被细节带着走。1.1 一个个人财务系统必须包含哪些功能个人财务系统听起来名字挺大但落到功能上核心其实就是一条记录每一笔钱的进出并能让人看懂钱花到哪去了。基于这个定位我把它拆成几个模块账户管理用户注册、登录、个人信息维护。既然是个人系统就不做复杂的角色权限单用户模型足够。账单管理每笔账单包含金额、类型收入/支出、分类、备注、记账时间。这里要支持新增、编辑、删除、分页查询是最核心的 CRUD 模块。分类管理支出分类如餐饮、交通、购物、居住收入分类如工资、兼职、理财收益。分类建议做成内置默认 用户自定义两层。预算管理对某一类支出设置月度上限比如本月餐饮预算 1500 元超过阈值时给出提醒。统计报表按月查看总收支、分类占比、趋势曲线。这部分是财务系统区别于普通记事本的关键也是最容易做砸的地方。以上功能看起来都不难但彼此之间是有依赖关系的。比如统计报表必须依赖账单的金额和分类维度预算管理必须依赖账单的金额和记账时间。所以设计表结构的时候就得先把这些维度想清楚否则后期加字段比重新建表还痛苦。1.2 为什么是 SpringBoot Android 这个组合如果单纯想做一个能用的记账工具微信小程序或者纯 Web 页面更快。但为什么要选 SpringBoot 原生 Android我的判断是这样的技术栈覆盖面广后端 SpringBoot 涉及 RESTful API 设计、MyBatis 持久层、JWT 认证、SQL 聚合统计前端涉及 Activity/Fragment 生命周期、网络请求封装、本地存储、图表组件。一套项目下来前后端主流知识点都触碰到了。就业市场认可度高Java 后端 Android 客户端这个组合在二线城市和传统软件公司依然是需求大头用它做毕设或者项目经验在简历里写面试官通常不需要额外脑补技术背景。移动端使用场景真实记账这个动作天然发生在掏出手机随手记一笔的场景里。用 Android App 承载这个业务比 Web 端更有说服力——这也方便我在答辩或展示时讲清楚为什么不做成网页。当然这个组合也有它的代价最明显的就是联调成本两端代码在两个工程里接口约定一旦变改起来是双倍工作量。所以后面我在接口设计上特别强调约定优先、文档同步这些都是实战里换来的教训。1.3 技术栈里每个组件的职责分配SpringBoot 2.7.x负责提供 RESTful API、业务逻辑处理和数据库操作。为什么不用 3.x3.0 之后基线是 JDK17很多学校机房和旧教程还是 JDK8版本不匹配会白花时间在环境配置上。2.7 是 Spring Boot 2.x 的最终版本稳定且资源最多。MyBatis持久层框架。相比 JPA/HibernateMyBatis SQL 是自己写的统计这类复杂查询更容易控制排查问题也直观。MySQL 8.0数据存储。金额字段用 decimal时间字段用 datetime这是财务系统的基本要求后面会细讲。Android 原生 Java客户端实现。网络层用 Retrofit2 OkHttp3图表用 MPAndroidChart本地存储用 SharedPreferences 保存登录态。JWTjjwt 库用户认证。无状态登录方案服务端不需要存 SessionAndroid 端拿到 Token 后放在请求头里携带。一句话总结技术选型逻辑不求最新但求文档多、坑少、容易说清楚。这一点对拿来做毕业设计的同学尤其重要答辩时老师问为什么用这个技术你能答出因为它的生态和稳定性适合这个场景远比因为最新版要有说服力。2. 后端设计从数据表到接口的完整落地过程后端做得好不好直接决定 Android 端开发是否顺畅。我见过太多项目接口文档不清楚、返回格式不统一、状态码含义模糊Android 端同学只能靠猜来联调最后做成一场灾难。这一章讲讲我在表结构和接口上的具体做法。2.1 数据库表结构设计字段、类型与索引的取舍先说明一下个人财务系统属于业务逻辑比较规整的应用表不要贪多核心四张表 一张用户表足够覆盖需求了。我当时的建表思路如下-- 用户表 CREATE TABLE t_user ( id int NOT NULL AUTO_INCREMENT COMMENT 主键, username varchar(50) NOT NULL COMMENT 用户名, password varchar(255) NOT NULL COMMENT 密码(BCrypt加密), nickname varchar(50) DEFAULT NULL COMMENT 昵称, create_time datetime DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间, PRIMARY KEY (id), UNIQUE KEY uk_username (username) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT用户表; -- 分类表 CREATE TABLE t_category ( id int NOT NULL AUTO_INCREMENT, user_id int NOT NULL COMMENT 所属用户, name varchar(20) NOT NULL COMMENT 分类名称, type tinyint NOT NULL COMMENT 1-收入 0-支出, is_default tinyint DEFAULT 0 COMMENT 是否系统内置, create_time datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT收支分类表; -- 账单表 CREATE TABLE t_bill ( id int NOT NULL AUTO_INCREMENT, user_id int NOT NULL, category_id int NOT NULL COMMENT 分类ID, amount decimal(10,2) NOT NULL COMMENT 金额, type tinyint NOT NULL COMMENT 1-收入 0-支出, remark varchar(255) DEFAULT NULL COMMENT 备注, bill_time datetime NOT NULL COMMENT 记账时间, create_time datetime DEFAULT CURRENT_TIMESTAMP, update_time datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, deleted tinyint DEFAULT 0 COMMENT 逻辑删除标记, PRIMARY KEY (id), KEY idx_user_time (user_id, bill_time), KEY idx_user_category (user_id, category_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT账单表; -- 预算表 CREATE TABLE t_budget ( id int NOT NULL AUTO_INCREMENT, user_id int NOT NULL, category_id int NOT NULL, amount decimal(10,2) NOT NULL COMMENT 月度预算金额, month varchar(7) NOT NULL COMMENT 预算月份 如2024-06, update_time datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY uk_user_cat_month (user_id, category_id, month) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT月度预算表;几个容易出问题的点我单独说一下金额必须用 decimalfloat/double 在二进制中无法精确表示做金额累加会出现 0.1 0.2 0.30000000000000004 这种问题。财务系统连这种低级错误都不能有。记账时间用业务时间而不是创建时间用户可能补录昨天甚至上周的账单统计报表必须以bill_time为准。很多新手错把create_time当记账时间去统计数据一多就乱了。账单表加deleted逻辑删除删除账单时不直接物理删行而是打标记。为什么因为月度统计、年度统计都依赖历史数据物理删除会让历史报表缺数据再者误删后还能恢复对用户友好的系统该有这个设计。索引设计要贴合查询路径最常用的查询是查某用户某段时间的账单所以建了(user_id, bill_time)复合索引统计分类汇总时走(user_id, category_id)。没有索引数据量过了几万后查询会肉眼可见地变慢。2.2 接口设计与统一返回格式约定后端接口的设计目标就一条让 Android 端同学不看后端代码也能把功能写完。所以第一步是定死统一返回结构。public class ResultT { private Integer code; // 200 成功400 业务错误401 未登录500 系统异常 private String message; // 提示信息 private T data; // 具体数据 // getter/setter/构造方法省略 }这样 Android 端解析 JSON 时只看code就能判断请求是否成功数据体data里放什么则由每个接口的文档说明。实际项目中我喜欢配合ControllerAdvice做全局异常处理业务异常抛出时自动转换成Result避免每个 Controller 里都要 try-catch。主要接口列表大概是这样的模块请求方式路径说明用户POST/api/user/register注册用户POST/api/user/login登录返回 Token分类GET/api/category/list获取当前用户的分类列表分类POST/api/category/add新增自定义分类账单POST/api/bill/add新增账单账单GET/api/bill/list分页查询账单账单PUT/api/bill/update编辑账单账单DELETE/api/bill/delete/{id}删除账单统计GET/api/stat/month?month2024-06月度收支汇总统计GET/api/stat/category?month2024-06分类占比统计预算POST/api/budget/set设置月度预算预算GET/api/budget/status?month2024-06查询预算使用情况分页这块我强烈建议用统一的PageResultT对象包含total、pages、records三个字段不要图省事直接把 List 返回给前端。因为移动端列表页一般都需要上拉加载更多没有总条数就没法判断是否还有下一页。2.3 关键业务逻辑统计与预算的计算为什么要放在后端账单多了以后统计报告就成了一件听起来简单、写起来讲究的事。我的原则是所有聚合计算一律在后端完成Android 端只负责展示。原因有两个一是 SQL 的聚合函数比在 Java 里手工循环累加高效得多也准确得多二是财务规则比如收入支出互斥、预算超额判定是业务的一部分放在后端才能保证多端行为一致。月度收支汇总的核心 SQL 可以写成这样select idselectMonthSummary resultTypemap SELECT IFNULL(SUM(CASE WHEN type 1 THEN amount ELSE 0 END), 0) AS total_income, IFNULL(SUM(CASE WHEN type 0 THEN amount ELSE 0 END), 0) AS total_expense FROM t_bill WHERE user_id #{userId} AND deleted 0 AND DATE_FORMAT(bill_time, %Y-%m) #{month} /select分类占比统计则需要按分类分组select idselectCategorySummary resultTypemap SELECT c.name AS category_name, SUM(b.amount) AS amount FROM t_bill b LEFT JOIN t_category c ON b.category_id c.id WHERE b.user_id #{userId} AND b.deleted 0 AND b.type 0 AND DATE_FORMAT(b.bill_time, %Y-%m) #{month} GROUP BY b.category_id, c.name ORDER BY amount DESC /select预算状态查询的逻辑是先查预算表拿预算金额再查账单表算当月已支出金额两者一除得出使用比例超过 100% 就返回over_budget true。这个逻辑用 Java Service 层两个查询一拼就能实现关键是事务与时机预算表和账单表不是同一个时刻写入的数据不要用事务去强行锁一致性最终结果能反映最新状态就行。后端这块还有个细节登录认证用拦截器统一做 Token 校验。我写了一个JwtInterceptor从请求头Authorization里取 Token解析成功才放行失败返回 401。这样每个接口的业务代码里完全不用关心当前用户是谁这种横切关注点只要在拦截器里把userId塞进请求上下文比如用ThreadLocal即可。3. Android 端实现从网络层到界面渲染的核心环节后端接口就绪后Android 端的工作量其实更大因为移动端要考虑的东西更碎网络请求的封装、登录态维持、Activity 生命周期、ListView/RecyclerView 的数据绑定、图表的交互体验……每一项都直接影响 App 好不好用。这一章按我实际的开发顺序来讲。3.1 工程结构与网络层封装我建 Android 项目时首选的包结构是按功能分层而不是按层分包。什么意思就是com.example.finance.ui.account、com.example.finance.ui.bill这种按页面模块分包比activity、adapter、fragment这种按类类型分包要直观得多。因为 Android 项目里一个功能页面往往由 Activity/Fragment Adapter ViewModel 组成按功能聚在一起改一个功能时不需要在十几个包之间来回跳。网络层的封装是重头戏核心代码如下// 通用的 Retrofit 构建器 public class RetrofitClient { private static Retrofit retrofit null; public static Retrofit getInstance() { if (retrofit null) { synchronized (RetrofitClient.class) { if (retrofit null) { OkHttpClient client new OkHttpClient.Builder() .addInterceptor(new HeaderInterceptor()) // 自动附加Token .connectTimeout(10, TimeUnit.SECONDS) .readTimeout(10, TimeUnit.SECONDS) .build(); retrofit new Retrofit.Builder() .baseUrl(BuildConfig.API_BASE_URL) .client(client) .addConverterFactory(GsonConverterFactory.create()) .build(); } } } return retrofit; } }HeaderInterceptor 是维持登录态的关键它从本地存储里取 Token每次请求自动加进 Header这样业务代码里完全不用手动传 Tokenpublic class HeaderInterceptor implements Interceptor { Override public Response intercept(Chain chain) throws IOException { Request request chain.request(); String token SharedPrefsUtil.getInstance().getToken(); if (!TextUtils.isEmpty(token)) { request request.newBuilder() .header(Authorization, Bearer token) .build(); } return chain.proceed(request); } }3.2 登录与 Token 失效处理细节决定体验登录流程是一个 App 最容不得含糊的环节。我的处理方式是登录接口成功后把返回的 Token 和用户基本信息写入 SharedPreferences每次请求如果收到 401 响应就清理本地登录态并跳转回登录页。这里有个很多新手会踩的坑直接在 Activity 里做 Token 判断。正确做法是在网络层统一处理。我用一个简单的回调包装器实现在 Retrofit 的 ResponseBody 解析前先看 HTTP 状态码如果被拦截器返回了 401就通过EventBus发一个全局事件任何界面收到事件都回登录页。这样做的好处是不用每个界面单独写失效逻辑代码干净很多。另外本地存储不建议用 SQLite 存 Token——杀鸡用牛刀。SharedPreferences 足够且简单配合 AES 加密存储就更稳妥了。要注意的是 SharedPreferences 不跨进程使用本项目单进程场景足够。3.3 记账流程与分类选择器把用户操作路径走顺记账页是整个 App 交互最核心的页面。我的交互设计是顶部是金额输入区一个大号 EditText 限制只能输入数字和小数点且最多保留两位小数。中间是分类网格通过 RecyclerView GridLayoutManager 实现每个分类是个图标加文字。默认展示支出分类点击右上角切换收入/支出分类列表动态刷新。底部是日期选择器和备注输入框日期默认今天可点击弹出 DatePickerDialog。点击保存按钮后调用/api/bill/add成功后带结果回列表页并刷新。这个页面最大的技术点在于分类数据的管理。用户在第一次进入记账页时界面会加载一次/api/category/list然后缓存到内存和本地。当用户自建了分类下次进入也要能看到。我建议用一个简单的数据单例管理分类列表因为分类不会频繁变化内存缓存可以避免重复请求。金额输入校验这块我记得调了很久。Android 的 EditText 设置android:inputTypenumberDecimal可以弹出数字键盘但它允许用户输入像1.2.3这样的非法值。所以 save 之前必须用正则校验private boolean isAmountValid(String amount) { return amount.matches(^\\d(\\.\\d{1,2})?$); }3.4 统计报表在移动端的渲染复现后端的聚合结果统计报表页我用的是 MPAndroidChart 库这也是 Android 图表组件里文档最丰富、用得最多的选择。具体做法月度收支总览用柱状图左边一根收入柱右边一根支出柱图下方用 TextView 显示结余金额。分类占比用饼图中心显示当月总支出点击某一块高亮该分类详情。预算执行进度用横向进度条ProgressBar 自定义样式的形式简单明了不一定要用图表库。图表数据的获取我只需要调用/api/stat/month和/api/stat/category两个接口返回的 JSON 结构例如{ code: 200, message: ok, data: { totalIncome: 8500.00, totalExpense: 6230.50, net: 2269.50 } }拿到数据后需要注意的是图表控件的数据绑定要在 UI 线程执行。用 Retrofit 回调默认是主线程设计enqueue的 onResponse 在 Android 主线程所以直接设置就没问题。但如果你自己起了子线程请求数据再回传就必须用runOnUiThread或 ViewModel 的 PostValue否则会崩在 Only the original thread that created a view hierarchy can touch its views。统计页还有个容易忽略的点日期切换。我默认显示当前月但提供了左右滑动的箭头切换上个月/下个月。每次切换月份都要重新请求一次统计数据。这里最好加一个下拉刷新 进度加载的反馈因为统计接口是聚合查询大数据量时可能慢几百毫秒用户没有反馈会觉得点了没反应。4. 部署联调与避坑记录跑通整个项目过程中的真实问题跑完整个项目趁记忆新鲜把踩过的坑写下来。这些问题如果没人提醒轮到你自己撞上的时候少则一下午多则一整天。4.1 环境版本匹配SpringBoot 与 Android 工具的隐性问题先说后端。SpringBoot 选 2.7.x 对应 JDK8 是我吃过教训后的选择。之前试过 SpringBoot 3.0 JDK17结果发现很多老教程的依赖写法在 3.x 里被改掉了比如javax.*变成jakarta.*网上搜到的解决方案一半是 2.x 的对不上就白折腾。2.7 可以无损使用 JDK8文档多、坑都被踩平了对新手非常友好。Android 端更折腾。Android Studio、Gradle、AGP、compileSdk 之间必须互相匹配。一个经典的版本坑是compileSdk 34 配上低版本的 AGP会直接报 Dependency ... requires libraries and applications that depend on it to compile against version 34。我当时卡了很久最后查了官方兼容表才解决。我实测可用的一套组合是组件版本JDK8后端/ 11Android 默认Android StudioHedgehog 或更新版本Gradle7.6 或 8.2AGP7.4.2 或 8.1.0compileSdk / targetSdk33 / 33minSdk21另一个几乎人人都遇的坑是Gradle 依赖下载慢。国内网络条件下google() 和 mavenCentral() 仓库经常卡住。我的做法是改用国内镜像仓库把build.gradle里的仓库地址替换成阿里云镜像速度立刻起飞。这一步写在文档里非常加分因为凡是照着你文档操作的人都会遇到同一个问题。4.2 真机联调与模拟器的区别网络地址与明文流量联调是最容易让人抓狂的环节。开发时后端跑在电脑上Android 模拟器访问宿主机要用10.0.2.2而不是localhost或127.0.0.1。模拟器里的 localhost 是模拟器自己所以如果你在 Android 代码里写http://localhost:8080后端其实是收不到请求的。正确写法是http://10.0.2.2:8080。如果用的是真机那问题又不一样了。真机不能访问10.0.2.2必须写你电脑的局域网 IP比如http://192.168.1.100:8080而且手机和电脑要连同一个 WiFi。这时要注意手机厂商的通过 WLAN 扫描可能挡住连接还有 Windows 防火墙默认拦截 Java 程序的 8080 端口入站请求需要在防火墙设置里允许。还有一个被无数人忽略的硬规则Android 9API 28开始默认禁止明文 HTTP 流量。App 访问http://接口会直接报 CLEARTEXT communication not permitted。解决方式是在AndroidManifest.xml的 application 标签里加android:usesCleartextTraffictrue或者用更规范的 networkSecurityConfig 只对调试地址放开明文权限。我当时图省事用了前者但正式发布前一定要改成只对开发环境放开不然有安全审查风险。4.3 日期与金额精度财务系统最容易被扣分的两个隐雷日期问题在统计接口里特别容易翻车。后端用Date类型返回时JSON 序列化后是2024-06-01 12:00:00还是时间戳Java 时区与 MySQL 时区不一致时查询结果差 8 小时的经典问题也会出现。我的经验是后端application.yml里明确配置serverTimezoneAsia/Shanghai和 Jackson 的日期格式。MySQL 连接串加useUnicodetruecharacterEncodingutf8避免中文乱码。Android 端解析金额统一用BigDecimal接 JSON 时用double过渡只是为了展示参与计算必须先转 BigDecimal。关于日期格式化Android 端用SimpleDateFormat有个著名的坑它在大写YYYY周所在的年和小写yyyy日历年上行为不同。跨年时YYYY-MM-dd会把 2023 年 12 月 30 日解析成 2024 年。项目里曾因为这个 bug 导致统计报表在 1 月初错乱排查半小时才发现是这个细节。建议直接用java.time.LocalDate和DateTimeFormatterAPI 26 以上或者用android.text.format.DateFormat安全得多。5. 源码、文档、演示视频怎么配合使用才高效拿到一个带源码文档运行视频讲解视频的项目如果直接打开跑其实效率很低。我通常会按照先看文档结构 → 再看数据库 → 再跑后端 → 再跑前端 → 最后看视频验证细节的顺序来。这个顺序对学习者和准备二次开发的人都适用。5.1 拿到项目后的正确上手顺序第一步是通读文档目录。好的项目文档通常包含环境要求、数据库初始化脚本、接口说明、部署步骤。先花 20 分钟把这些看完知道自己要准备什么比如 JDK 版本、MySQL 账号密码然后再去配环境比一边配环境一边翻文档要快得多。第二步是把数据库脚本跑起来。找到 init.sql 或 create_database.sql打开看一眼结构确认表数量和字段命名再执行导入。这一步能让你对系统的数据模型有个整体认识后面看代码时看到category_id不会懵。第三步是启动后端。修改application.yml里的数据库连接信息运行 Application 类用 Postman 或浏览器先访问一个测试接口确认 200。这里建议直接测试登录接口拿到一个 Token再去调别的接口看返回结构这能验证你环境里后端没问题。第四步才是跑 Android。把工程导入 Android Studio等 Gradle 同步完成检查build.gradle里的 API_BASE_URL 配置然后运行到模拟器或真机。视频的利用时机在这里很关键看运行视频是为了知道预期结果长什么样看讲解视频是为了知道你刚才在代码里看到的某个类到底担当什么职责。建议先照着文档跑通一次再遇到问题时针对性地看讲解视频对应段落这样带着问题看效率最高。5.2 文档和视频各自的侧重点与学习路径源码是最终的事实依据。所有怎么做的答案最后都要在源码里找。读源码时注意看包结构、关键类职责、接口调用链路。数据库脚本是数据的说明书也是设计思想的浓缩。表关系、字段含义、索引设计都在里面。文档是中间的粘合剂。它告诉你环境怎么搭、接口怎么调属于操作手册。运行视频偏验证性质。展示 App 跑起来后的界面效果、功能流程、数据变化适合在答辩或汇报时快速回顾。讲解视频偏理解性质。解释关键实现思路、设计原因、前后端交互过程适合为什么层面遇到的问题。对准备答辩的同学我的建议是把讲解视频里涉及的为什么这么设计的问题整理成问答列表比如为什么预算表用唯一索引防止重复为什么统计接口返回一个聚合对象而不是列表。这些是老师最爱问的点提前准备能省不少现场组织的压力。5.3 如何基于这个模板扩展成自己的项目拿到项目不要只想着原样跑通那就浪费了。个人财务系统这个基础架构往上扩展的空间其实很大我提供几个我实践过或身边人做过的方向数据导出增加一个导出 Excel 账单功能后端用 EasyExcel 生成文件Android 端下载后发送到分享或直接用文件管理器查看。这个功能实现简单且实用性极强。多账户管理在现有基础上增加银行卡/现金/支付宝等账户维度账单关联账户 ID统计时支持按账户筛选。这是从个人流水升级为资产管理的关键一步表结构和统计逻辑都要动。图表增强把月度统计扩展为最近 6 个月收支趋势折线图查看消费趋势。这个改动主要在 Android 端后端加一个按月返回 6 个点的接口即可。数据同步与备份使用 WebSocket 或 WorkManager 定时把本地未同步的账单推送到后端支持多设备数据同步。这个方向适合进阶。做扩展时注意一个原则先加字段再加逻辑。比如多账户管理第一步是给t_bill表加account_id外键第二步才是改统计 SQL。循序渐进别一上来就动核心结构。最后分享一个我个人的实操体会财务系统这类项目的完整度比技术难度更重要。一个功能齐全、逻辑自洽、界面统一、文档清晰的系统哪怕技术用的都是基本功在展示和答辩中也比一个堆砌了微服务但只跑通一个页面 Demo 的项目加分得多。Java springboot 基于 Android 的个人财务系统恰恰就是一个能把完整度做到很高的选题。拿到源码后不要着急改功能先把每条接口请求的链路从头到尾走通再从最简单的点开始扩展这个过程本身就是一次比看任何教程都扎实的全栈训练。
返回列表