简介一套基于前后端分离架构的Java家庭理财系统完整源码包面向具备Java基础、希望学习Spring Boot与Spring Cloud微服务项目的开发者以及需要快速搭建个人财务记录与分析场景的实践者。系统覆盖支出与收入统计、类型图表分析、股市与基金走势追踪、已买股票及基金管理、外债记录、固定资产与房贷车贷核算以及月末和年末报表等家庭理财核心模块。包内共246个文件主要包含57个java后端业务类、66个js与58个jsx前端页面组件、18个xml配置、12个less样式、9个yml服务配置以及sql数据库脚本等压缩包仅4.48MB结构紧凑、层次清晰。当前已有537人学习下载适合通过阅读源码掌握多模块业务落地、前后端数据交互、微服务环境搭建与报表展示等实用技能。1. 这套 Java 家庭理财系统Spring Boot React 前后端分离到底值不值得下如果你搜到这个资源多半正在做 Java 课程设计或者想找个前后端分离的真实项目练手。这套家庭理财系统源码不是那种只有几个页面的玩具 demo它把支出、收入、股票、基金、外债、固定资产、月末年末报表全串在了一条业务链上后端用 Spring Boot 2.0.7 SpringCloud Finchley.SR2前端用 React 16 Ant Design Pro 4.0Redis 做缓存、RabbitMQ 走消息数据库用 MySQL 5.7。换句话说这是一个「麻雀虽小但五脏俱全」的企业级骨架你改一改就能直接当课设答辩项目或者作为 Spring Boot 微服务入门的学习蓝本。本文不打算念 PPT我会直接把这个项目从技术选型、本地启动、模块拆解到常见报错一条条掰开讲清楚照着做就能跑起来。2. 技术栈和项目架构为什么这套系统要用前后端分离加微服务2.1 前后端分离结构怎么理解这套项目不是把 Java 页面塞进 JSP 里而是完全的前后端分离。后端只提供 RESTful API前端是一个独立的 React 工程。两者通过 JSON 交互所以你在源码里会看到一个后端模块和一个前端工程目录需要分别启动。为什么要这么设计先看业务场景。家庭理财涉及收支流水、图表统计、股票基金行情同步还有月末年末报表。如果做成单体 JSP页面渲染、数据计算、报表聚合全部耦合在一起改一个饼图样式可能要把整个 tomcat 重启一遍。前后端分离后前端只管渲染 Echarts 图表后端只处理数据和业务逻辑联调时只要接口约定好两端可以并行开发。这也是为什么这套系统后端自带 Swagger 风格的接口文档配置前端有独立的 mock 数据目录。2.2 版本选型为什么是这些数字这套系统的版本号很有讲究值得先看懂再动手。Spring Boot 用的是 2.0.7SpringCloud 是 Finchley.SR2这两个版本是官方测试过的稳定搭配。如果你的机器上装了更高版本的 JDK这里就是一个大坑——JDK 11 以上跑 Spring Boot 2.0.7 经常出现反射相关的兼容性问题后面我会详细说。数据库用 MySQL 5.7.30Redis 6.0.8这两个都是当时主流的生产版本。RabbitMQ 3.4 负责异步消息主要是通知类场景。有人可能会问现在都 Spring Boot 3 了为什么还要用 2.0.7答案很简单这套源码是课程设计型的完整工程它选的不是最新而是最稳。3.x 的配置项好多都改了比如spring.fastdfs.nginx.host这类自定义配置在 2.x 里是常见写法拿到 3.x 上跑反而会大量报错。所以如果你只是要一个能跑能答辩的项目请严格按它的原版 JDK 1.8 MySQL 5.7 Redis 6 来搭环境。2.3 目录结构里藏着哪些模块下载源码后你看到的不是一个扁平目录而是几个层次分明的工程。后端工程里按职责做了分包常见结构是 controller、service、mapper、entity 四层。业务上分为用户管理、支出管理、收入管理、股票基金、外债、固定资产、报表几大块其中 UserIncomeServiceImpl.java、UserExpensesServiceImpl.java、UserExpensesController.java 这几个文件是核心入口——支出和收入是系统的地基其他模块都建立在它们之上。前端工程基于 Ant Design Pro 4.0 搭建页面结构按业务划分比如支出页面、收入页面、股市页面、基金页面、报表页面。这种分包方式的好处是你想改哪块业务从前端页面到后端接口是一条直线不用满工程翻代码。你就把后端当成一个大工厂每个 controller 是一个车间service 是车间里的具体工序mapper 是仓库管理员——数据进出全靠它。我刚拿到这套源码的时候最先做的事不是执行任何代码而是把后端 application.yml 从头到尾读了一遍。里面写了端口、数据库连接池、Redis 地址、RabbitMQ 地址、还有静态资源映射路径。这一步不能省因为很多启动失败的问题根源都在这个配置文件里。3. 把项目跑起来本地部署步骤与参数调优3.1 环境准备清单开始部署之前先把环境检查一遍。这套系统依赖的东西比较多如果漏装任何一个启动时都会报莫名其妙的错。下面是我建议的安装清单和版本匹配直接对着来。依赖组件推荐版本用途JDK1.8.0_251运行后端 Spring Boot其他版本会踩兼容性坑Maven3.6.3构建后端工程、管理依赖MySQL5.7.30持久化业务数据Redis6.0.8缓存用户会话、热点数据、排行榜RabbitMQ3.4异步消息队列用于通知类业务Nginx1.14.2静态页面代理、反向代理后端接口Node.js8.x 或 10.x构建 React 前端工程提示Node 版本千万别装最新的 18 或 20Ant Design Pro 4.0 构建时对 Node 版本有隐性要求太高会直接构建失败。这个坑我后面排查章节细说。3.2 后端启动步骤与参数说明后端启动的第一个关键操作是导入数据库脚本。在源码的 sql 目录下找到建库建表脚本用 MySQL 命令行或者 Navicat 执行。然后修改后端工程里的 application.yml核心配置如下。server: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/family_finance?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/Shanghai username: root password: 123456 driver-class-name: com.mysql.jdbc.Driver redis: host: localhost port: 6379 database: 0 rabbitmq: host: localhost port: 5672 username: guest password: guest这段配置里有几个容易踩的雷区。useSSLfalse建议保留如果改成 true而本机 MySQL 没配 SSL 证书连接会直接失败。serverTimezoneAsia/Shanghai必须带上否则日期字段查询结果会比实际时间少 8 小时做月末报表的时候数据永远对不上。RabbitMQ 的 guest 账号默认只能在 localhost 登录不要自作主张改成远程 IP。配置文件改好后在 maven 窗口先执行clean再执行install跳过测试用例命令是mvn clean install -DskipTests。这一步会把所有依赖 jar 包装进本地仓库。如果网络不好第一次构建可能耗时很久这是正常现象不需要焦虑。构建成功后再启动 Spring Boot 的 main 方法或者用mvn spring-boot:run。启动完成后观察控制台。Tomcat started on port(s): 8080 (http) with context path Started FamilyFinanceApplication in 12.345 seconds看到这行日志说明后端就绪了。但这一步不是终点还要做一个验证。打开浏览器访问http://localhost:8080/actuator/health。如果返回{status:UP}证明 Spring Boot 和数据库连接、Redis 连接都正常。如果 status 是 DOWN按下面的启动排查清单检查。检查项正常标志常见的错误标志MySQL 服务3306 端口可连接Communications link failureRedis 服务6379 端口可连接redis-cli ping返回 PONGUnable to connect to RedisRabbitMQ5672 端口可连接Connection refused数据库脚本表存在且数据可查询Table doesnt exist补充一个我实际遇到过的问题。数据库脚本成功执行后访问登录接口仍然报 401。后来发现是脚本里密码字段的加密方式与后端代码的加密方式不一致——建表脚本用的明文而后端登录校验用的是 MD5 加盐密文。遇到这种情况别急着改代码先到数据库里看种子数据的密码是不是已经被加密过。一般课设项目的 sql 脚本里都会自带一条管理员账号比如 admin / admin123但密码字段可能是一串 32 位 MD5 值。如果你发现是明文就找后端里密码校验的工具类把管理员密码生成一份密文再 update 进去这是最稳妥的做法。3.3 前端启动步骤与参数说明后端跑通之后进入前端工程目录。安装依赖构建并启动开发服务器。npm config set registry https://registry.npm.taobao.org npm install npm start第一条命令设置镜像源国内网络下速度快很多第二条安装全部 npm 依赖Ant Design Pro 项目依赖数量比较多八百到一千个包很正常装几分钟才到 100% 都是常见情况第三条启动开发服务器默认端口是 8000。启动成功后控制台会显示Project is running at http://localhost:8000/。前端启动后还需要确认一个代理配置。在config/config.ts或者.umirc.ts里找到 proxy 配置确认前端请求的/api前缀能不能转发到后端 8080 端口。常见写法是这样proxy: { /api: { target: http://localhost:8080, changeOrigin: true, }, }changeOrigin: true很关键。后端接口在鉴权时如果校验了请求头里的 Host不加这个字段转发就会被后端判定为非法请求。很多新手前端页面能打开但所有接口都返回跨域错误或 403问题几乎都出在这个参数上。前端启动后浏览器访问http://localhost:8000能看到登录页面就说明 web 层通了。然后输入管理员账号密码如果登录成功跳转到首页并且首页上的本日支出、本月收入、股市走势图等卡片都有数据就说明整个链路——浏览器到前端、前端到后端、后端到数据库——全部打通了。3.4 Nginx 部署方式如果你只是本地开发开发服务器就够了。但如果你想模拟真实部署或者答辩时直接通过域名访问那么可以用 Nginx 做静态托管和反向代理。把前端工程执行npm run build产物在dist目录下。然后写一份 Nginx 配置。server { listen 80; server_name localhost; root /usr/share/nginx/html/dist; index index.html; location / { try_files $uri $uri/ /index.html; } location /api/ { proxy_pass http://localhost:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }try_files这一行是前端路由的关键。React 项目用的是 history 路由刷新某个子页面时 Nginx 会去磁盘找对应的路径找不到就直接 404。加了try_files $uri $uri/ /index.html会让所有请求回退到首页由前端路由接管。如果你部署后刷页面就白屏一定先检查这一行有没有写。4. 核心业务模块拆解收支、股票基金、外债与报表怎么落地4.1 支出与收入系统的主干逻辑这套系统的业务主脑是支出和收入所有的图表分析、报表统计都派生自这两个模块。支出模块在 UserExpensesServiceImpl.java 里它不只是简单的增删改查还把支出数据按「本日、本月、本年」三个粒度做了聚合同时生成支出类型分析图。后端做了一个典型的 service 层聚合操作大致逻辑如下。public MapString, Object getExpenseSummary(String userId) { MapString, Object result new HashMap(); // 本日支出查当天0点到当前时间的数据 BigDecimal todayExpense expensesMapper.sumByDateRange(userId, DateUtils.getTodayStart(), new Date()); // 本月支出查本月1号到当前时间 BigDecimal monthExpense expensesMapper.sumByDateRange(userId, DateUtils.getMonthStart(), new Date()); // 本年支出查本年1月1号 BigDecimal yearExpense expensesMapper.sumByDateRange(userId, DateUtils.getYearStart(), new Date()); result.put(today, todayExpense); result.put(month, monthExpense); result.put(year, yearExpense); return result; }这个代码看起来简单但有三点值得注意。第一三个统计都复用了同一个 sumByDateRange 方法只是入参不同这比写三个 SQL 要优雅得多也给后续维护留了余地。第二DateUtils 里求「今天开始」「本月开始」「本年开始」的方法注意是用 Calendar 还是 LocalDate。JDK 1.8 环境里两种都能用但Calendar.getInstance()在多线程环境下如果被静态共享会出现日期错乱。第三SQL 里对日期的比较用的是和 第二天零点而不是当天 23:59:59避免秒级精度导致边界数据被漏掉。收入模块 UserIncomeServiceImpl.java 走的也是类似逻辑但聚合维度稍微少一些只做了本月和本年统计。为什么收入不按「本日」统计因为系统设计者的业务逻辑是工资、理财收益等收入不是每天都有按「日」统计没有实际意义。这是一个很真实的取舍做课设时你在论文里能把这种设计思路写出来答辩成绩会不一样。4.2 股票和基金行情数据怎么展示股票模块和基金模块是这类系统里最抓眼球的部分。很多同学以为它是实时对接了股票 API实际上课设项目大概率是从接口拉一次缓存下来或者内置了模拟数据。你去看工程里的定时任务或初始化逻辑会发现它的设计思路是每隔一段时间刷新一次行情数据存入 Redis 或 MySQL前端展示时直接读库。已买股票、已买基金这两个子功能的增删改查是真实业务。用户的每一笔交易记录会有买入价格、数量、买入日期系统根据最新行情计算浮动盈亏。这块的核心参数在交易表里关键字段包括代码、名称、方向、价格、数量、手续费、时间戳。这里我多说一句很多课设代码里「计算当前市值」是写死的假数据不是通过实时接口算的。如果你仔细读接口发现它从后端返回的 currentPrice 是固定值不要觉得被坑了——这是课设项目的普遍情况因为对接实时行情接口需要申请 API key且调用次数有限。答辩时你说清楚「当前是演示数据预留了替换为真实行情的接口位」老师反而会觉得你考虑周全。4.3 外债和固定资产容易被忽略但工作量大的模块外债模块分借出和借入两本账这个设计对家庭理财场景很实用。借出是别人欠你的钱借入是你欠别人的钱两个方向不能混在一起否则月末报表里资产负债情况全乱。这个模块还涉及还款计划还款日期到了需要提醒Redis 在这里起了缓存作用RabbitMQ 在这里扮演了生成通知的角色。固定资产模块又分房贷车贷和全款两类是设计和实现里最繁琐的部分。房贷车贷要维护贷款总额、已还期数、每期还款金额、剩余本金全款资产要记录购买日期、购置价格、当前估值。月末报表会把这些资产汇总算出家庭净资产趋势。这一类实体的数据模型通常更复杂嵌套了好几层写 mapper XML 的时候容易因为字段没映射全导致报表计算出 null。4.4 报表月末与年末的核心实现这套系统的报表模块是整份源码的「权力中心」它把前面所有业务模块的数据汇总起来。月末报表统计当月的支出、收入、结余按支出类型算占比年末报表在这基础上加上了全年的趋势比对、资产负债汇总。报表逻辑常见的实现方式是用一个专门的 Service 类调用多个 mapper 的方法取数再在内存里做汇总。这种方式的好处是不需要写复杂 SQL逻辑都在 Java 里可控坏处是如果数据量大内存开销会高但对于家庭个人记账的场景绰绰有余。关键实现思路是先汇总支出明细再汇总收入明细再查固定资产和外债数据把它们全部封装成一个报表 VO 对象返回前端。前端用 Echarts 渲染柱状图和饼图时最需要的字段就是分类名、金额、占比正好和这个 VO 对应。5. 部署避坑指南五个常见问题与排查方法5.1 启动时报「No active profile set」和端口占用现象后端启动控制台提示No active profile set, falling back to default profiles: default紧接着报Port 8080 was already in use。原因存在两个问题。第一个是 application.yml 里没有配置 spring.profiles.active系统只能走默认配置。第二个是 8080 端口被占用了一般是之前残留的 Java 进程没退干净。解决端口被占用时Linux/Mac 执行lsof -i:8080找到进程 PID 后 kill 掉Windows 执行netstat -ano | findstr 8080找到 PID 后用任务管理器结束。profile 的问题不用太紧张如果没有多环境配置需求默认配置可以直接用但建议在 yml 里加一行spring.profiles.active: dev让日志更清晰。5.2 MySQL 连接报「Public Key Retrieval is not allowed」现象后端启动连数据库时控制台报错Public Key Retrieval is not allowed。原因MySQL 5.7 及以上版本默认使用 caching_sha2_password 插件JDBC 第一次连接需要获取 RSA 公钥但连接串里没有授权允许。之前我遇到过一个人明明其他项目都能连数据库偏偏这个工程报错他还以为数据库坏了。实际上是他直接复制的配置文件没改连接串而原来的项目用的是 mysql_native_password 用户。解决在 jdbc 连接串最后加一个参数。jdbc:mysql://localhost:3306/family_finance?useSSLfalseallowPublicKeyRetrievaltrueallowPublicKeyRetrievaltrue明确允许 JDBC 从服务器获取公钥。如果加了还报错就检查 MySQL 用户插件类型执行ALTER USER rootlocalhost IDENTIFIED WITH mysql_native_password BY 你的密码;。5.3 前端 npm install 安装到一半卡死现象执行npm install后进度条长时间停在某一处或者报错ETIMEDOUT。原因npm 默认源在国外访问不稳定是常见问题不是在下载超大文件。解决把 npm 源切到国内镜像然后删除 node_modules 重新装。npm config set registry https://registry.npm.taobao.org rm -rf node_modules package-lock.json npm install这里特别提醒不要手动删除单个依赖包名然后重新装有时候 node_modules 里的残留会导致依赖树不一致干脆整体删除再来一遍最干净这个逻辑和 Maven 里mvn clean是一样的。5.4 登录后页面能打开但所有列表接口返回 404现象前端登录成功也跳转到了首页但页面上所有表格都报 404控制台里能看到/api/expense/list这个请求是 404。原因实际是前端请求路径和后端 controller 映射的路径不一致。Ant Design Pro 里的 request 默认会带/api前缀如果后端的 RequestMapping 没有包含这个前缀Spring Boot 就找不到对应的处理函数。解决优先看前端 request 工具里有没有封装统一前缀如果有后端所有 Controller 的类上就统一加/api前缀。不要逐个接口去加在application.yml里配置全局路由前缀是最省事的。server: servlet: context-path: /api加了 context-path 之后所有接口路径会自动带/api前缀前端无需改动。但要注意这种方式会造成静态资源路径也要加/api才能访问如果是前后端分离项目本项目的后端可能不托管页面影响不大。5.5 Node 版本过高导致前端构建直接崩溃现象执行npm start时报错SyntaxError: Unexpected token ?或者Digital Envelope routines::unsupported。原因Node 17 及以上版本使用 OpenSSL 3.0而 Ant Design Pro 4.0 依赖的 webpack 4.x 还在用 OpenSSL 1.x 的 hash 算法。前端构建工具链太老跟新版 Node 的底层库不兼容。这个报错极其经典几乎所有玩 webpack4 老项目的人都会碰到。解决最省心的方法是把 Node 版本切到 10.x 或 12.x用 nvm 来管理。nvm install 12.22.12 nvm use 12.22.12如果你不想切换 Node 版本可以尝试在启动命令前加一个环境变量export NODE_OPTIONS--openssl-legacy-provider npm start这个方案能让你不用换 Node 版本就绕过 OpenSSL 的问题但治标不治本。后面的依赖安装或者升级时还会不会有其他兼容性问题谁也说不准。从稳定性角度我强烈建议直接切 Node 12。6. 进阶用法把「月末报表」扩展成 Excel 导出与全年动态对比这套系统的报表模块虽然功能已经比较完整但它呈现方式局限在网页图表里。如果你想在答辩时展示额外的工程能力或者这个系统你自己真的要用起来我建议加一个数据导出功能——把当月报表直接导出成 Excel 文件。这是一个封闭业务闭环的硬需求报表只停留在屏幕上你就没法做二次加工或者打印。实现思路不复杂。后端在报表接口旁边新增一个导出接口用 POI 或者 EasyExcel 生成文件流返回给前端。推荐用 EasyExcel依赖轻量、API 简单对课程设计来说更容易讲清楚。核心代码如下。GetMapping(/report/export) public void exportMonthlyReport(RequestParam String month, HttpServletResponse response) throws IOException { // 查本月收支汇总 ReportVO report reportService.generateMonthlyReport(month); ListExpenseItem expenseList report.getExpenseList(); response.setContentType(application/vnd.ms-excel); response.setCharacterEncoding(utf-8); String fileName URLEncoder.encode(月末报表_ month .xlsx, UTF-8); response.setHeader(Content-Disposition, attachment;filename fileName); ExcelWriter writer EasyExcel.write(response.getOutputStream(), ExpenseItem.class) .sheet(支出明细) .build(); WriteSheet sheet EasyExcel.writerSheet(支出明细).build(); writer.write(expenseList, sheet); writer.finish(); }这段代码做了一件事查询指定月份的所有支出数据以 Excel 附件形式返回给前端。contentType用来告诉浏览器这是一个需要下载的文件filename用 URLEncoder 编码避免浏览器把中文文件名解析成乱码EasyExcel.write方法的第一个参数直接是 response 的输出流意味着文件不会落地到服务器磁盘而是实时吐给前端。这个细节在答辩时值得单独讲因为它体现了你对内存和 IO 的理解。前端页面加一个下载按钮请求这个接口时会弹出文件保存框。这样一来数据分析就不局限于网页内了你完全可以把数据放进本地的 Excel 里做二次透视。整套系统从数据录入、图表展示、报表汇总到导出存档就形成了完整的闭环。从那以后我做这类管理系统的课设项目都强制把「导出」功能加进交付清单里因为数据出得去系统才真正有用。希望帮到你。本文还有配套的精品资源点击获取