ARTICLE DETAIL

资讯详情

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

Java+Swing+MySQL教务管理系统实战:从环境配置到避坑指南

Java+Swing+MySQL教务管理系统实战:从环境配置到避坑指南 简介这是一份基于Java Swing与MySQL的学校教务管理系统源码包面向正在完成Java课程设计或期末大作业的学生也适合想了解桌面端管理系统搭建的开发者。压缩包共39个文件其中包含25个Java源文件、6张界面运行截图、5个XML配置文件、1个SQL数据库脚本以及说明文档可覆盖系统核心代码、界面展示、工程配置与数据库初始化等环节整体大小240KB轻量且便于直接导入开发工具运行。该资源已有218人学习下载源码经本地编译可运行且评审得分为98分内容由助教老师审定难度适中能满足学习与实战需求。借助这份资料可以直观理解Swing界面与MySQL数据交互的完整流程学习学生、课程、成绩等教务管理模块的设计思路同时参考工程目录结构提升课程设计与毕业设计的质量。1. JavaSwingMySQL教务管理系统一个能跑通的期末大作业长什么样如果你现在正为期末大作业发愁下载了一个 JavaSwing 的教务管理系统源码包心里想的是“能不能直接交”。我的回答是能但前提是你得知道它内部怎么走通。这套 JavaSwingMysql 学校教务管理系统面向课程设计和期末大作业的常见场景管理员维护学生、教师与课程教师录成绩学生查成绩。它用桌面窗体替代网页登录界面、菜单栏、数据表格一应俱全既不用搭建 Web 服务器也不需要引入 Spring 之类的框架适合在答辩现场直接演示。很多课设包的问题不是代码错而是下载后没人告诉你第一步做什么。数据库脚本放在哪连接配置写在哪主类在哪默认账号是什么这些信息往往比代码本身更值钱。这篇笔记就是来解决这件事的我会把这份已编译可运行的资源拆成一份可复现的手顺从 JDBC 连接讲到 JTable 刷新再到容易翻车的几个坑。适合人群是正在赶课的本科生实习初期想补 Swing 的从业者也能拿它当桌面临摹。2. 系统拆解为什么Swing JDBC MySQL这套组合最省事2.1 选型理由Swing不是过时是课程设计的“保底答案”写课程设计最怕的不是功能难而是技术栈选了之后自己讲不明白。Swing 从 JDK 1.2 就有了论新潮拼不过 JavaFX论企业味拼不过 Spring Boot但正因为老反而成了最稳定的课设选择。老师课件里常见 Swing社区里关于它的报错记录也最全任何一个异常你都能搜到对应解法。更关键的是Swing 属于 Java 标准类库不需要额外装客户端环境打包成 jar 双击就能看到界面这对答辩演示特别友好。另一方面数据库选 MySQL 而不是文件存储理由也很实际。MySQL 安装门槛低导出 sql 脚本就能交给别人复现教务管理系统天然适合关系模型学生、课程、成绩之间有明确的外键逻辑。使用 JDBC 直连最直接连接串加上用户名密码三行配置就能通。如果换成 MyBatis 或 Hibernate反而会让课程设计的重点偏离到框架配置上。所以在评审老师眼里Swing JDBC MySQL 这个组合传递的信息是这个人懂面向对象界面设计懂基本数据库操作具备最朴素的桌面软件开发能力。对一份期末大作业来说这已经足够。2.2 项目结构从pom.xml到educational_admin.sql解压后的根目录结构是这样的。pom.xml 是 Maven 的工程描述文件它决定依赖版本和打包方式educational_admin.sql 是数据库初始化脚本表结构和初始数据都在里面src/main/java 放源码src/test 放着可以忽略的测试类target 是编译输出目录。README.md 通常记录了运行说明建议第一件事先打开它。操作顺序我一般这样定打开 pom.xml确认 JDK 版本和 MySQL 驱动版本。用 MySQL 执行 educational_admin.sql建立数据库。打开 src/main/java 搜索 jdbc:mysql定位 DBUtil 或 db.properties。修改账号密码后再运行主类。这个顺序不是随便定的。我经常看到有人直接右键运行主类结果报“数据库连接失败”回头才发现根本没执行 sql 文件。先把数据库准备到位登录界面的后续逻辑才有意义。下面这张表格是压缩包里几个关键文件的作用也可以帮助你回答“项目分为哪些部分”。文件或目录作用重点关注pom.xmlMaven 依赖管理mysql-connector-java 版本educational_admin.sql建库建表与初始数据管理员账号初始值src/main/java源码主目录实体类、DAO、界面类src/test测试代码一般忽略README.md运行说明与项目介绍默认账号信息用 Maven 而不是直接把 jar 塞进 lib是因为依赖可以自动下载换一台电脑也能一键还原。如果压缩包里没有 pom.xml只有 src 和 jar 文件说明原工程是 Eclipse 传统方式此时要在 Module Settings 里手动引入 mysql jar。2.3 数据表设计五张表怎么撑起一个教务系统很多人的误区是觉得教务系统很复杂其实课设哪需要几十张表。一份合格的教务管理系统通常用五张表就能覆盖全部业务。学生表存学生身份与个人信息教师表存教师工号与姓名课程表存课程名、学分和开课教师成绩表记录学生与课程的关联分数管理员表只用来登录后台。这五张表的关系可以用一句话描述学生通过选课动作在成绩表中与课程建立多对多关系。学生表的主键是 stu_id教师表是 teacher_id课程表是 course_id。成绩表用自增 id 做主键再用唯一键约束同一学生同一课程只能存在一条记录。CREATE DATABASE IF NOT EXISTS educational_admin DEFAULT CHARACTER SET utf8mb4; USE educational_admin; CREATE TABLE t_teacher ( teacher_id VARCHAR(20) PRIMARY KEY, username VARCHAR(32) UNIQUE NOT NULL, password VARCHAR(64) NOT NULL, name VARCHAR(50) NOT NULL, title VARCHAR(20) ) ENGINEInnoDB; CREATE TABLE t_course ( course_id VARCHAR(20) PRIMARY KEY, course_name VARCHAR(50) NOT NULL, teacher_id VARCHAR(20), credit INT DEFAULT 2, max_stu INT DEFAULT 30 ) ENGINEInnoDB; CREATE TABLE t_score ( id INT PRIMARY KEY AUTO_INCREMENT, stu_id VARCHAR(20) NOT NULL, course_id VARCHAR(20) NOT NULL, score DECIMAL(5,2), UNIQUE KEY uk_stu_course (stu_id, course_id) ) ENGINEInnoDB;这段 SQL 里的细节都有意义。ENGINEInnoDB 支持事务与外键虽然课设不一定会显式用事务但成绩批量录入时InnoDB 能保证行锁和回滚能力。DEFAULT CHARACTER SET utf8mb4 直接决定中文能不能存进去utf8mb4 比 utf8 多了对 emoji 的支持是目前建库更稳的写法。UNIQUE KEY uk_stu_course 是核心约束可以防止代码写错导致同一学生重复选同一门课。表结构在不同版本里可能略有差异例如有些包会额外加一个选课表专门记录选课时间。这没有问题只是设计习惯不同。拿到 SQL 后先不要动字段跑通再改。2.4 功能模块与权限边界在不看代码之前先把它从业务上拆成三层。登录层负责角色分流主窗体负责菜单导航各管理模块负责增删改查。常见的分配是管理员能进学生管理、教师管理、课程管理和成绩管理教师只能进成绩录入和自己课程的学生列表学生只能查成绩和个人信息。这种设计在界面实现上往往不是严格权限系统而是通过登录后传一个 role 字符串主窗体根据角色隐藏某些菜单项。代码层要控制权限只需要在按钮监听器里加一个 if 判断。懂得这个逻辑后答辩时被问“怎么防止学生进入教师界面”你就能回答第一层界面隐藏第二层监听器校验若想更稳可以在 DAO 层把角色作为查询条件不必引入 Spring Security。3. 本地复现从JDK配置到打开登录窗口的完整流程3.1 环境准备与版本选择先定版本JDK 8、MySQL 5.7 或 8.0、IDEA 2020 以上。JDK 8 是课设圈的共识稳定性好Swing 组件在 8 上运行没有任何问题Maven 插件兼容性也好。如果你电脑已经装了更高版本的 JDK比如 17只要 pom.xml 里 maven.compiler.source/target 还是 1.8就会出现编译风格不匹配建议直接把项目 SDK 切到 1.8。MySQL 版本要注意驱动类名。mysql-connector-java 5.x 对应的驱动类是 com.mysql.jdbc.Driver8.x 对应的是 com.mysql.cj.jdbc.Driver。如果代码里写的是 5.x 的类名却连的是 8.x MySQL运行时会提示 Could not create connection to database server。最稳的做法是打开 pom.xml 看依赖版本把整个 JDBC 组合统一成下面这套。软件建议版本关键配置JDK1.8JAVA_HOME 指到 1.8MySQL5.7 或 8.0root 密码自己设定mysql-connector-java8.0.33驱动类 com.mysql.cj.jdbc.DriverIDEA2020 以上用 Open 打开 pom.xml环境变量只需要确认java -version能输出 1.8 即可。网上很多 MySQL 安装教程会顺手让你改环境变量但 Java 项目里 MySQL 不需要额外配置关键是 root 密码要和源码里的 DBUtil 保持一致。推荐安装时直接把密码设为 123456与源码默认配置对齐能省掉很多麻烦。3.2 初始化数据库与配置文件拿到源码后先到命令行执行初始化脚本mysql -uroot -p educational_admin.sql mysql -uroot -p -e USE educational_admin; SHOW TABLES;第一条命令把整个脚本导入 MySQL。第二条命令用 -e 参数执行查询列出所有表。如果看到 t_admin、t_teacher、t_student、t_course、t_score 之类的输出说明初始化成功。此处 -p 参数会提示输入密码输入 123456 回车即可。如果在 Windows 命令行手输密码很麻烦也可以在 MySQL 客户端里执行source D:/educational_admin.sql;source 命令要求斜杠路径注意不要加引号。执行完再查一下数据SELECT * FROM t_admin;应该能看到一行初始化账号。多数课设包的默认管理员是 admin/admin123如果查询为空说明脚本里不含初始数据需要手动执行一条 INSERT。3.3 在 IDEA 里导入并运行打开 IDEA用 Open 或 Import Project 选择解压后的根目录。关键一步在导入向导里选择 Maven 项目而不是单纯作为普通 Java 工程。这样 IDEA 才会根据 pom.xml 自动解析依赖。右侧 Maven 面板出现项目结构后等待依赖下载完成。接着修改数据库连接配置。搜索jdbc:mysql定位到 DBUtil 类确保三个参数和本机一致Class.forName(com.mysql.cj.jdbc.Driver); String url jdbc:mysql://localhost:3306/educational_admin?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai; String user root; String password 123456;其中 Class.forName 负责加载驱动类只要 pom.xml 依赖里有对应 jar就不会抛 NoClassDefFoundError。characterEncodingutf8 让 JDBC 以 UTF-8 编码读写数据中文不乱码。serverTimezoneAsia/Shanghai 是 MySQL 8.x 必须加的时区参数不加会报时区异常。改完配置后找到主类类名通常是 LoginFrame、MainFrame 或 Start。右键运行看到 Swing 登录窗口弹出就是第二阶段成功。用 t_admin 表里的初始账号登录如果报错回到第二章看 SQL 是否真的执行而不是急着改代码。3.4 命令行编译与运行如果不想用 IDEA命令行也可以跑通。这种方式操作多但对理解 classpath 很有帮助也适合导师要求在没有 IDE 的机器上演示的场景。先用 Maven 编译mvn clean package -DskipTests在 target 目录下会生成 jar 文件。如果主类没有在 pom.xml 里配置运行前需要指定主类名java -cp target/xxx.jar;mysql-connector-java-xxx.jar com.example.LoginFrame这里的 -cp 在 Windows 下用分号分隔Linux 或 macOS 下要换成冒号。如果不把 mysql 驱动 jar 放进 classpath运行时必然报 ClassNotFoundException。这个命令值得练习一次因为答辩时如果评委问“你打的包能不能脱离 IDEA 运行”回答起来会更有底气。3.5 复现失败时的排查顺序我见过最多的复现失败场景不是代码被故意改了而是环境没对齐。按下面的顺序排查大部分问题能解决确认 MySQL 服务是否启动。Windows 下看任务管理器有没有 mysqld 进程macOS 下用brew services list。确认能否用 Navicat 或命令行连接 MySQL。连不上时先解决 root 密码问题。看控制台报错类型。SQLException 多半在连接或 SQL 语法ClassCastException 多半是表字段类型与实体类不一致。确认 JDK 版本。Project Structure 里的 SDK 改成 1.8。确认 3306 端口没被占用。如果 MySQL 改成 3307JDBC URL 也要同步改。4. 核心代码解读从PreparedStatement到事务边界4.1 登录逻辑PreparedStatement和按角色分流Swing 登录窗体的构成很简单两个输入框一个下拉框或单选按钮一个登录按钮。点击按钮后的事件里做三件事先做非空校验再根据角色选择对应表最后用 PreparedStatement 查询。下面这段代码是一个完整还原你会发现它和很多课设包的写法几乎一致public void login(JTextField userField, JPasswordField pwdField, String role) { String username userField.getText().trim(); String password new String(pwdField.getPassword()).trim(); if (username.isEmpty() || password.isEmpty()) { JOptionPane.showMessageDialog(null, 用户名和密码不能为空); return; } Connection conn null; PreparedStatement ps null; ResultSet rs null; try { conn DBUtil.getConnection(); String table t_admin; if (学生.equals(role)) { table t_student; } else if (教师.equals(role)) { table t_teacher; } String sql SELECT username FROM table WHERE username ? AND password ?; ps conn.prepareStatement(sql); ps.setString(1, username); ps.setString(2, password); rs ps.executeQuery(); if (rs.next()) { JOptionPane.showMessageDialog(null, 登录成功); // new MainFrame(username, role).setVisible(true); } else { JOptionPane.showMessageDialog(null, 用户名或密码错误); } } catch (Exception e) { e.printStackTrace(); } finally { try { if (rs ! null) rs.close(); } catch (Exception ignored) {} try { if (ps ! null) ps.close(); } catch (Exception ignored) {} try { if (conn ! null) conn.close(); } catch (Exception ignored) {} } }这里有两个值得注意的细节。第一个是 PreparedStatement 的?占位符用户名和密码都通过 setString 绑定已经能避开 SQL 注入。前提是不要在 SQL 里用字符串拼接用户输入。表名部分直接拼进 SQL 并没有注入风险因为 role 字段来自代码内部的下拉框选项而不是自由文本框。第二个是 finally 块里的三个 close。Connection、PreparedStatement、ResultSet 都必须关闭顺序是从里到外。如果忘记关闭长时间运行会把连接耗尽表现为系统用一段时间后登录变慢。课程设计的数据量让这个问题不容易暴露但答辩被问到连接管理时能答出来很加分。4.2 学生管理JTable刷新与动态条件查询学生管理窗口是典型的上方搜索框、中间表格、下方按钮布局。点击查询后系统按学号或姓名模糊搜索并刷新 JTable。添加和编辑按钮弹出一个小的 JDialog里面放学生信息输入框确认后执行 insert 或 update。删除按钮执行 delete。三个操作完成后都需要刷新表格数据重要程度仅次于 SQL 本身。我把查询刷新逻辑写成独立的loadStudentData(String condition)方法。每次操作后直接调用它不需要重新构建 JTable 对象。这样做的目的是让 JTable 的 TableModel 始终与数据库保持一致。一个常见的翻车点是很多人直接在按钮事件里写table.setModel(new DefaultTableModel())结果列头和数据错位。更稳的做法是定义自己的实体列表然后通过 Model 类把列表灌进去public void loadStudentData(String condition) { ListStudent list new ArrayList(); String sql SELECT * FROM t_student; if (condition ! null !condition.trim().isEmpty()) { sql WHERE name LIKE ? OR stu_id LIKE ?; } try (Connection conn DBUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { if (condition ! null !condition.trim().isEmpty()) { String like % condition.trim() %; ps.setString(1, like); ps.setString(2, like); } ResultSet rs ps.executeQuery(); while (rs.next()) { Student s new Student(); s.setStuId(rs.getString(stu_id)); s.setName(rs.getString(name)); s.setSex(rs.getString(sex)); s.setMajor(rs.getString(major)); list.add(s); } StudentTableModel model new StudentTableModel(list); table.setModel(model); } catch (SQLException e) { e.printStackTrace(); } }这段代码里使用了 try-with-resources连接与语句能自动关闭。关键在于 StudentTableModel 是自定义的 AbstractTableModel 子类它的构造函数接收ListStudent并把列表里的字段映射成列名。如果你不想新建类也可以直接用 DefaultTableModel但那样数据与 UI 的耦合度更高。当 condition 为空时sql 就是全量查询不为空时LIKE ?配合%实现前后模糊匹配。LIKE 在 MySQL 中的通配符是%与_如果用户输入了%会被当成通配符。课设阶段不必处理面试被问到 SQL 相关八股时你可以答“用 escape 转义即可”。4.3 选课与成绩事务与去重选课模块的核心是两件事判断课程是否还有名额判断学生是否已选过。前者不能只靠 max_stu 字段要看成绩表里已存在的记录数后者既要在 Java 层查重也要靠数据库唯一键兜底。下面这段是简化的事务式选课写法public boolean selectCourse(String stuId, String courseId) { String checkCount SELECT COUNT(*) FROM t_score WHERE course_id ?; String checkDup SELECT COUNT(*) FROM t_score WHERE stu_id ? AND course_id ?; String insertSql INSERT INTO t_score(stu_id, course_id, score) VALUES (?, ?, NULL); Connection conn null; PreparedStatement ps null; ResultSet rs null; try { conn DBUtil.getConnection(); conn.setAutoCommit(false); ps conn.prepareStatement(checkCount); ps.setString(1, courseId); rs ps.executeQuery(); rs.next(); int selected rs.getInt(1); int max getCourseMaxStu(courseId); if (selected max) { conn.rollback(); return false; } ps conn.prepareStatement(checkDup); ps.setString(1, stuId); ps.setString(2, courseId); rs ps.executeQuery(); rs.next(); if (rs.getInt(1) 0) { conn.rollback(); return false; } ps conn.prepareStatement(insertSql); ps.setString(1, stuId); ps.setString(2, courseId); ps.executeUpdate(); conn.commit(); return true; } catch (Exception e) { try { if (conn ! null) conn.rollback(); } catch (Exception ignored) {} e.printStackTrace(); return false; } finally { try { if (rs ! null) rs.close(); } catch (Exception ignored) {} try { if (ps ! null) ps.close(); } catch (Exception ignored) {} try { if (conn ! null) { conn.setAutoCommit(true); conn.close(); } } catch (Exception ignored) {} } }这里的核心是 setAutoCommit(false) 与 commit()。如果不开启事务第一步检查通过、第二步插入失败就会多出一条不完整的中间记录。事务让两步操作要么同时成功要么一起回滚这也是课设答辩里“数据一致性”的答案。注意在 finally 里要把 autoCommit 恢复成 true否则连接归还后下一位使用者会继承关闭事务的奇怪状态。成绩录入与选课是同一个套路无非把 score 从 NULL 改成具体分数SQL 就是常见的UPDATE t_score SET score ? WHERE stu_id ? AND course_id ?最终同样走 commit 与 rollback。如果你觉得事务样板代码太重复可以把开启、提交、回滚封装成一个小工具类这也是一个可以写进答辩稿的改进点。4.4 DBUtil 与连接池改造大多数课设包的 DBUtil 长这样静态代码块加载驱动getConnection 方法返回 DriverManager.getConnection(url, user, password)。这种写法在几十个并发下也没问题但做成真实系统会扛不住多用户同时点查询。我一般建议把它写成独立的单例不引入第三方连接池public class DBUtil { private static final String URL jdbc:mysql://localhost:3306/educational_admin?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai; private static final String USER root; private static final String PASSWORD 123456; public static Connection getConnection() throws SQLException { return DriverManager.getConnection(URL, USER, PASSWORD); } }如果你在答辩时被问“连接是每次都创建吗”可以回答正式系统会用连接池复用课程设计为了简洁直接创建。因为 Swing 界面本身是桌面客户端连接数极少这样的设计完全够用。5. 避坑指南教务系统从运行到答辩的五个常见问题跑通服务只是第一步评审现场翻车往往发生在你意想不到的细节上。这一章我整理的是从环境配置到打包演示最常见的五个坑每一条都按现象、原因、解决三个层次展开。后面遇到类似问题可以先翻到对应小节对照。5.1 现象Could not create connection to database server原因通常是 MySQL 版本是 8.x但驱动类名还是 com.mysql.jdbc.Driver或者 URL 缺少 serverTimezone 参数。解决方法是把 DBUtil 里的驱动类改为 com.mysql.cj.jdbc.Driver数据库连接 URL 改成jdbc:mysql://localhost:3306/educational_admin?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai然后刷新 Maven 依赖重新执行。如果 pom.xml 里的 mysql-connector-java 版本还是 5.x建议升级到 8.0.33。这个报错经常被误判成 MySQL 没启动其实打开控制台看完整堆栈就会发现第一行是 Unknown database 还是 Access denied前者是库不存在后者才是密码问题。遇到这类问题先区分是连接层还是认证层能省很多时间。5.2 现象页面中文全部乱码数据写入变成问号原因有两个层面。第一是建库字符集不是 utf8mb4第二是 JDBC URL 少了 characterEncodingutf8。解决方法是先执行ALTER DATABASE educational_admin DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;再重建已经乱码的表。如果数据已经写入只能在重建表后重新插入。另外还要检查源码文件编码。IDEA 右下角能看到当前文件编码如果源码是 GBK 却按 UTF-8 打开界面上的中文会直接变成乱码。把 File Encodings 里的 Global Encoding、Project Encoding、Default encoding for properties 都改成 UTF-8然后重启项目。乱码问题我习惯在初始化数据库之后立即自测而不是等界面跑起来才看这样能定位问题在 JDBC 还是界面层。5.3 现象运行报 ClassNotFoundException: com.mysql.jdbc.Driver原因就是 mysql-connector jar 不在 classpath 中或者项目根本没有引用这个依赖。解决方法是打开 pom.xml确认是否包含 mysql-connector-java 依赖如果是传统工程右键 jar 文件选择 Add as Library并选对 Module。我一般会额外执行一次mvn dependency:resolve检查依赖是否全部下载完成避免 IDEA 偶尔出现的下载中断。这个报错的隐蔽版本是“找不到主类”那只说明项目构建没成功编译输出目录里没有 class 文件。先 clean 再 package往往就能解决。5.4 现象点击删除按钮后数据库没了但 JTable 不刷新原因不是 SQL 没执行而是删除成功后没有重新加载表格数据。解决办法是把loadStudentData(null)放到删除成功分支的最后一行也可以统一封装一个 refresh 方法所有增删改成功后都调用它。不要在每次按钮事件里重新 new JTable这样内存里会出现大量废弃组件。我见过有人加了一行table.revalidate()以为这样能刷新结果表格数据还是旧的。真正要做的是重新执行 SELECT 并 setModel。要记住 JTable 只负责显示数据模型里的 List 不更新界面上永远看不到最新状态。5.5 现象打成可执行 jar 后图片加载失败或界面卡顿用 IDE 运行一切正常但用mvn clean package打包后双击 jar窗体图片不显示甚至界面卡顿。原因通常是资源路径写成了文件系统相对路径比如src/main/resources/logo.png打包后这个路径在 jar 里根本不存在。解决方法是把图片放进src/main/resources/images加载时用getClass().getResource(/images/logo.png)。界面卡顿则是因为 JTable 模型更新过于频繁比如在循环里反复 setModel。正确做法是只设置一次模型后续通过自定义 TableModel 的 setData 方法更新数据源再调用 table.updateUI 或 model.fireTableDataChanged()。记住一个原则数据量决定 SQL界面刷新决定用户体验。5.6 排查技巧把异常写进日志而不是只打印到控制台Swing 程序最容易踩的坑是控制台报错一闪而过你以为没事结果作业提交后才发现逻辑没走对。我一般会在 DBUtil 里加一个简单的 Logger用 java.util.logging 输出到文件。哪怕只是把项目目录下的 error.log 指出来答辩时演示错误定位也是加分项。Logger logger Logger.getLogger(eduadmin); FileHandler fh new FileHandler(eduadmin.log, true); fh.setFormatter(new SimpleFormatter()); logger.addHandler(fh);这段代码会在当前目录生成日志文件。遇到异常时用 logger.severe(e.getMessage())而不是直接 e.printStackTrace()。这样打包给老师看时系统行为有迹可循也能帮你下次复现时直接翻日志不用花时间猜测。6. 进阶与答辩把课设从“能跑”改到“能讲”6.1 三个见效最快的改进点如果时间只够做三个改进我建议按顺序给密码做 MD5、加入选课名额判断、做一个操作日志区。第一个改进让系统的安全性可直接被描述第二个让业务逻辑更完整第三个让界面看起来像真实系统。下面这段是 MD5 封装public static String md5(String source) { StringBuilder sb new StringBuilder(); try { MessageDigest md MessageDigest.getInstance(MD5); byte[] bytes md.digest(source.getBytes(UTF-8)); for (byte b : bytes) { sb.append(String.format(%02x, b)); } } catch (Exception e) { e.printStackTrace(); } return sb.toString(); }调用时把登录密码替换成md5(password)同时把初始数据中的密码也改成同样的 32 位 MD5 串。注意登录验证需要数据库密码也是 MD5否则永远验证失败。这个改进成本不高答辩时却能很自然地回答“如何避免明文存储”。选课名额判断就是把第四章的事务代码用起来在插入前统计 t_score 中课程数量与 t_course.max_stu 比较。操作日志区可以放一个 JTextArea每次增删改成功后 append 一条带有时间戳的记录。这三个改进做完整个系统的完成度立刻不一样。6.2 答辩时怎么讲这套系统的设计思路评审老师通常会问三个问题分层结构怎么设计事务怎么保证权限怎么做你可以用简短话术对应界面层只用 Swing数据访问层用 JDBC 封装业务规则放服务层成绩录入接口开启事务选课流程检查名额与重复不同角色登录后通过菜单可见性和监听器双重控制。不用把术语说得很大关键是每一句都能从代码里找到对应的位置。比如说到分层你可以直接打开代码窗口指出这个类是界面类这个类是 DAO这就是分层。说到事务把 4.3 里的 com.rollback 指给老师看比背一百遍理论都有说服力。6.3 把常驻 SQL 维护成常量类一个低成本但很有工程感的习惯是把散落在按钮监听器里的 SQL 字符串统一收集到一个 SQLConst 类。新建一个接口把常用查询串定义为字段比如String SELECT_STUDENT_BY_ID SELECT * FROM t_student WHERE stu_id ?。这能减少重复字符串也能避免以后改表名时全局搜索。做完这些再回头看这份 JavaSwingMysql 教务管理系统源码就不再是下载后原样上交的模板而是你能说明白每一个按钮、每一条 SQL 的作品。从那以后我每次拿到新的课设代码都会强制走一遍「先看 SQL、再改连接、最后跑主类」的顺序这个习惯帮我避开了很多环境层面的坑。希望这份教务管理系统源码能帮到你尽快跑通并交出一份自己讲得明白的作业。本文还有配套的精品资源点击获取
返回列表