
简介这是一套面向Java初学者与课程设计者的家庭记账系统完整源码基于JavaFX、MySQL、JDBC与MVC模式实现可作为JavaSE综合实践与毕业设计参考。系统包含用户注册登录、账单增删改查、数据写入文件及多线程处理等模块帮助理解界面编程、数据库持久化与分层架构的协作方式。压缩包共58个文件约986KB以15个java源文件与16个class字节码为核心辅以8个fxml界面布局、9个xml配置、1个sql建表脚本及mysql驱动jar另附说明文档与README目录按controller、dao、view、domain等分层组织结构清晰便于阅读与二次开发。目前已有50人学习下载适合具备一定Java基础、希望打通JavaFX与JDBC数据库应用开发的读者参考。1. 从一份 JavaSE 课设说起JavaFX MySQL 家庭记账系统能跑出什么很多 Java 初学者在学完语法后卡在同一个地方能写单文件小程序但一碰到「界面 数据库 分层」就不知道从哪下手。这份基于 JavaFX MySQL JDBC MVC 的家庭记账系统正好是一个能直接跑起来的完整样本。它把用户注册登录、账单增删改查、数据落库、账单导出到文件这几件事串成了一条线代码量不大但五脏俱全。适合两类人一是正在找 JavaSE 综合课设的学生二是想补一次「从界面到数据库全链路」实操的转行者。下面我按拆包顺序讲清楚它怎么用、参数怎么配、坑在哪。2. 拆开压缩包先看结构MVC 分层与 JDBC 连接的真实落点拿到housekeeper-project-master这个目录别急着用 IDEA 打开先花两分钟把结构看明白后面配环境能省一半时间。这个项目的分层是标准的 MVC 落地写法不是那种把 SQL 全塞进按钮事件里的假分层。2.1 目录结构与各层职责从项目正文给出的目录看核心代码集中在src下分成app、controller、dao、domain、view、tools几个包。这套划分对应 MVC 的经典映射目录/文件职责对应 MVC 角色domain实体类比如账单对象、用户对象Modeldao封装 JDBC 增删改查直接和 MySQL 打交道Model 的数据访问层controller接收界面事件调用 dao回填 viewControllerviewJavaFX 的 fxml 或纯代码界面Viewtools工具类常见是 JDBC 连接获取、文件写入基础设施lib/mysql-connector-java-5.1.46.jarMySQL 驱动包依赖SQLFile建库建表脚本数据库初始化管家婆软件说明.txt使用说明文档out/production是 IDEA 的编译输出目录.idea是工程配置这两个不用管。真正要动的是src、lib、SQLFile三块。这里有个选型上的点值得说驱动用的是mysql-connector-java-5.1.46这是 5.x 系列。它对应的是 MySQL 5.7 及更早版本的连接协议com.mysql.jdbc.Driver这个类名在 5.x 里有效。如果你本地装的是 MySQL 8.x直接拿这个驱动去连大概率会撞上时区和 SSL 的报错后面避坑章节会细讲。2.2 数据库初始化先跑 SQLFile 再谈连接在写任何 Java 代码之前先把数据库准备好。SQLFile目录里通常是.sql脚本用命令行或者 Navicat 执行都行。命令行方式最干净# 登录 MySQL注意 -p 后面直接跟密码不要有空格或者回车后交互输入 mysql -u root -p # 登录成功后先建库库名以脚本里的为准这里假设是 housekeeper CREATE DATABASE IF NOT EXISTS housekeeper DEFAULT CHARACTER SET utf8mb4; # 切到该库 USE housekeeper; # 执行建表脚本路径换成你本地的实际路径 source /your/path/SQLFile/housekeeper.sql; # 验证表是否建好 SHOW TABLES;逻辑说明CREATE DATABASE里的utf8mb4是为了兼容中文备注字段如果脚本里写的是utf8也能用但存 emoji 或生僻字会出问题。source命令是 MySQL 客户端内置的用来批量执行脚本文件比手动复制粘贴 SQL 稳。执行完SHOW TABLES应该能看到用户表和账单表两张如果只有一张说明脚本中途报错了往上翻日志找第一条 error。参数说明库名、表名以SQLFile里的实际内容为准我上面写的housekeeper只是示例。字符集建议统一utf8mb4排序规则用utf8mb4_general_ci即可家庭记账这种量级不需要纠结性能。2.3 JDBC 连接配置URL、驱动类、账号密码三件套数据库建好后去tools包里找连接工具类通常是JDBCUtils或DBUtil这种命名。里面会有类似下面的代码// 常见写法静态代码块加载驱动方法返回 Connection static { try { // 5.x 驱动的类名8.x 要换成 com.mysql.cj.jdbc.Driver Class.forName(com.mysql.jdbc.Driver); } catch (ClassNotFoundException e) { e.printStackTrace(); } } public static Connection getConnection() throws SQLException { // 关键参数库名、时区、字符编码、SSL String url jdbc:mysql://localhost:3306/housekeeper ?useUnicodetruecharacterEncodingutf8 useSSLfalseserverTimezoneAsia/Shanghai; return DriverManager.getConnection(url, root, 你的密码); }逻辑说明Class.forName是 JDBC 4.0 之前的显式加载方式5.x 驱动里保留着作用是让驱动类被类加载器加载并注册到DriverManager。getConnection返回的Connection会被 dao 层拿去创建PreparedStatement。参数说明useUnicodetruecharacterEncodingutf8保证中文不乱码useSSLfalse关掉 SSL 握手本地开发没必要开开了反而容易因为证书问题连不上serverTimezoneAsia/Shanghai是 8.x 驱动强制要求的5.x 驱动加不加都行但加上更保险能避免The server time zone value这类报错。账号密码换成你自己的别用 root 空密码跑虽然本地无所谓但养成习惯。3. 把项目跑起来IDEA 导入、驱动挂载与登录注册链路结构看明白后进入实操。这一章的目标是让你在 IDEA 里点下运行按钮看到登录窗口弹出来并且能注册一个新用户进库。3.1 IDEA 导入与依赖挂载这个项目是普通 JavaSE 工程不是 Maven 工程所以依赖要靠手动挂。步骤File - Open选中housekeeper-project-master目录IDEA 会识别成 Java 工程。打开Project Structure快捷键CtrlAltShiftS进Modules确认src被标记为 Sources。进Libraries点选Java把lib/mysql-connector-java-5.1.46.jar加进来。回到Modules - Dependencies确认这个 jar 在列表里且 scope 是 Compile。进Project确认 SDK 是 JDK 8 或 11。JavaFX 在 JDK 11 之后被移出标准库如果用的是 JDK 11需要额外配 JavaFX SDK 的 module pathJDK 8 则自带 JavaFX最省事。这里有个高频翻车点很多人导入后 jar 没挂上运行时报java.lang.ClassNotFoundException: com.mysql.jdbc.Driver。这不是代码问题是依赖没进 classpath。按上面第 3、4 步检查一遍即可。3.2 注册与登录两次密码校验与入库项目说明里提到「注册用户只需要两次输入的密码一致即可」说明注册逻辑不复杂核心是校验两次输入再插库。controller 里大概是这样// 注册按钮的事件处理伪代码结构 public void handleRegister() { String username usernameField.getText().trim(); String pwd1 passwordField1.getText(); String pwd2 passwordField2.getText(); // 两次密码一致性校验这是项目说明里强调的点 if (!pwd1.equals(pwd2)) { showAlert(两次密码不一致); return; } if (username.isEmpty() || pwd1.isEmpty()) { showAlert(用户名或密码不能为空); return; } // 调 dao 插入用户 boolean ok userDao.insert(new User(username, pwd1)); if (ok) { showAlert(注册成功请登录); } else { showAlert(注册失败用户名可能已存在); } }逻辑说明trim()去掉用户名首尾空格避免「admin」和「admin 」被当成两个用户。两次密码用equals比较不能用这是字符串比较的基本功。userDao.insert内部用PreparedStatement执行INSERT INTO user(username, password) VALUES(?, ?)占位符能防 SQL 注入虽然课设场景没人攻击你但这是该有的写法。参数说明用户名唯一性靠数据库表的唯一索引兜底如果建表脚本里没加UNIQUE那重复注册会成功登录时就会查出多条记录。建议去SQLFile里确认username字段有没有唯一约束没有的话手动加上ALTER TABLE user ADD UNIQUE KEY uk_username (username);登录逻辑对应的是SELECT * FROM user WHERE username? AND password?查得到就进主界面查不到提示错误。注意密码是明文存的课设够用但真实项目必须加盐哈希这点心里要有数。3.3 账单增删改查与文件导出登录进主界面后核心功能是账单的增删改查。账单实体一般包含日期、金额、类型收入/支出、备注几个字段。dao 层对应四个方法insert、delete、update、queryAll。controller 把表格选中行的数据取出来调对应方法然后刷新TableView。文件导出这块项目说明提到「可以写入到文件中」常见实现是把TableView里的数据遍历一遍用BufferedWriter写到 txt// 把账单列表导出到文件 public void exportToFile(ListBill bills, String path) { try (BufferedWriter bw new BufferedWriter( new OutputStreamWriter(new FileOutputStream(path), UTF-8))) { for (Bill b : bills) { // 用逗号分隔方便后续用 Excel 打开 bw.write(b.getDate() , b.getAmount() , b.getType() , b.getRemark()); bw.newLine(); } } catch (IOException e) { e.printStackTrace(); } }逻辑说明用 try-with-resources 自动关流避免忘记close导致文件句柄泄漏。OutputStreamWriter指定 UTF-8否则 Windows 默认 GBK导出的中文备注在别的机器上打开会乱码。每行一条记录逗号分隔直接改后缀成.csv就能用 Excel 打开。参数说明path建议用FileChooser让用户选保存位置而不是写死路径。金额字段如果是BigDecimaltoString()输出即可别用double拼接会有精度尾巴。4. 避坑与排查驱动版本、时区、乱码、JavaFX 缺失这四类最常撞这一章是我自己复现这类项目时踩过的坑按「现象 → 原因 → 解决」列出来你照着对号入座。现象一启动报java.lang.ClassNotFoundException: com.mysql.jdbc.Driver。原因驱动 jar 没挂进 classpath或者用的是 8.x 驱动但代码里写的还是 5.x 的类名。 解决先确认lib下的 jar 已在Modules - Dependencies里如果本地是 MySQL 8.x 且换了 8.x 驱动把类名改成com.mysql.cj.jdbc.DriverURL 里补上serverTimezone。现象二连接报The server time zone value ?D1ú±ê×?ê±?? is unrecognized。原因MySQL 服务端时区没配驱动拿到的时区字符串解析不了5.x 驱动在某些版本也会触发。 解决URL 里加serverTimezoneAsia/Shanghai或者登录 MySQL 执行SET GLOBAL time_zone 8:00;再重连。现象三账单备注里的中文存进库变成问号或者导出文件打开乱码。原因数据库、表、连接三处字符集不一致。常见是建库用了latin1或者连接 URL 没带characterEncoding。 解决建库建表统一utf8mb4URL 加useUnicodetruecharacterEncodingutf8导出文件用OutputStreamWriter指定 UTF-8。现象四JDK 11 运行报Error: JavaFX runtime components are missing。原因JDK 11 起 JavaFX 从标准库剥离需要单独引入。 解决最省事是切回 JDK 8如果必须用高版本去下 JavaFX SDK在 VM options 里加--module-path 你的javafx/lib路径 --add-modules javafx.controls,javafx.fxml。现象五注册成功但登录失败或者能注册重复用户名。原因username字段没有唯一约束或者登录 SQL 用了LIKE导致模糊匹配。 解决给username加唯一索引登录 SQL 用精确匹配别用LIKE。提示改完 SQL 或连接参数后记得重启应用JDBC 连接池如果有不会自动感知配置变化。5. 进阶玩法把明文密码换成哈希、给账单加统计与线程落库跑通之后这个项目还有几个能明显提升「含金量」的改造点也是面试时能聊的东西。第一个是密码安全。现在密码明文存库改成加盐哈希不难。用MessageDigest做 SHA-256注册时生成随机盐一起存登录时用同样方式算一遍比对// 注册时生成盐 哈希 public static String[] hashPassword(String raw) throws NoSuchAlgorithmException { byte[] saltBytes new byte[16]; new SecureRandom().nextBytes(saltBytes); String salt Base64.getEncoder().encodeToString(saltBytes); MessageDigest md MessageDigest.getInstance(SHA-256); md.update(saltBytes); byte[] digest md.digest(raw.getBytes(StandardCharsets.UTF_8)); String hash Base64.getEncoder().encodeToString(digest); return new String[]{salt, hash}; // 两个都存库 }逻辑说明盐是随机字节每个用户不同这样即使两个用户密码一样哈希结果也不同彩虹表失效。MessageDigest是 JDK 自带的不用引第三方库。参数说明盐长度 16 字节够用哈希算法 SHA-256 比 MD5 安全真实项目更推荐 BCrypt但课设用 SHA-256 加盐已经能说明你懂原理。第二个是账单统计。项目说明提到「包含一些基本线程的使用」可以顺着这个点做一个后台线程定时汇总当月收支// 后台线程每 30 秒刷新一次当月统计不阻塞 UI ScheduledExecutorService scheduler Executors.newSingleThreadScheduledExecutor(); scheduler.scheduleAtFixedRate(() - { BigDecimal income billDao.sumByType(收入, currentMonth); BigDecimal expense billDao.sumByType(支出, currentMonth); // Platform.runLater 把结果推回 UI 线程JavaFX 的 UI 更新必须在 FX 线程 Platform.runLater(() - { incomeLabel.setText(收入 income); expenseLabel.setText(支出 expense); }); }, 0, 30, TimeUnit.SECONDS);逻辑说明ScheduledExecutorService比Timer更稳单线程池够用。关键点是 JavaFX 的控件更新必须在 FX Application Thread 上做后台线程直接改Label会抛IllegalStateException所以要用Platform.runLater包一层。参数说明30 秒是刷新间隔按需调sumByType是 dao 里新增的聚合查询SQL 用SELECT SUM(amount) FROM bill WHERE type? AND DATE_FORMAT(date,%Y-%m)?。第三个是导出格式升级。把逗号分隔的 txt 换成真正的 CSV处理一下备注里本身带逗号的情况用双引号包裹字段。这个改动小但导出文件用 Excel 打开时不会错列体验差别很大。从那以后我每次拿到这类课设项目都强制先跑一遍SQLFile建库、再核对驱动版本和 URL 参数、最后才点运行这三步顺序反了就是无休止的报错。希望帮到你。本文还有配套的精品资源点击获取