简介:这是一份基于 GUI/Swing 与 MySQL 的商品库存管理系统 Java 课程设计资源,适合需要完成相关课设、快速入门桌面应用开发的学生使用。压缩包共 52 个文件、约 351KB,包含可直接导入运行的 Java 源码、编译后的 class 文件、数据库脚本 commodity.sql、课设报告 docx,以及登录账号密码说明,结构上按 src、out、img 等目录组织,方便阅读与提交。系统界面保持原始朴素风格,功能围绕商品与库存管理展开,满足常见课设要求,可直接运行演示或基于源码二次修改。目前已有 449 人浏览学习,对急需交付课设或复习 Swing/JDBC 编程具有一定的参考价值。资源来自实际接单项目,经过顾客运行验证,能够正常启动,适合作为过审课设的稳妥方案。
1. 商品库存管理系统:Java 课设最稳的 Swing + MySQL 组合
如果你正在为 Java 课程设计发愁,这个商品库存管理系统值得认真看一遍。它用的是经典的 GUI/Swing 桌面端加 MySQL 数据库,不是花哨的 Web 项目,技术栈完全对应课设大纲里最常出现的几个点:Swing 界面、JDBC 连接、SQL 脚本和数据展示。资源里带完整的源代码、数据库脚本 commodity.sql 和课设报告,环境配好就能直接跑。适合手里没有完整可运行源码、又想让老师现场点开就能演示的同学。不用刻意美化界面,能稳定运行、能讲清每个类的作用,往往才是通过课设的关键。
2. 跑通课设的第一关:环境选型与项目结构
2.1 为什么是 Swing + MySQL:课设评审最关心的技术点
Java 课设选 Swing,很多人觉得老,但它其实是风险最低的方案。Swing 从 JDK 1.2 开始就是标准库的一部分,不需要额外装 JavaFX SDK,也不需要配置复杂的模块化参数。老师课堂上讲过的组件基本都能直接套用:JFrame 做窗体、JTable 做列表、JTextField 做输入框、JButton 做按钮,这些组件拼起来就是一套完整的库存管理界面。相比之下,JavaFX 虽然界面更现代,但很多学校的实验环境里并没有装对应插件,课设答辩现场出问题的几率高不少。
MySQL 这边也一样,它是最容易装、学习资料最多的关系型数据库。课设里用 MySQL 存商品信息和登录账号,能直接体现 JDBC 编程能力。如果贪图简单用文本文件或对象序列化存数据,代码量是少了,但讲不出“数据表设计”和“SQL 查询”这两个课设必考点,分数很容易被压下去。反观 MySQL 8.0,安装包里自带可视化配置向导,驱动选 mysql-connector-java 8.0.x,整个链路是通的。
这套系统是 C/S 架构,也就是客户端加服务器。Swing 写客户端,MySQL 当服务器,两者通过 JDBC 通信。很多同学会担心,老师会不会觉得桌面端不如 Web 端高级?我的看法是:课设题目只写了“商品库存管理系统”,没限定必须用浏览器访问。桌面程序有自己的优势,比如双击就能运行、不需要启动 Tomcat、不占端口,演示的时候最少受外部环境影响。对答辩来说,稳定运行比技术栈新更重要。
还有一个容易被忽略的点:这份项目是纯 Java 工程,没有引入 Maven 或 Gradle,没有 SSH 框架,连配置文件都很少。这意味着你用 IDEA 直接打开源码目录,指定好 JDK,再导一个 MySQL 驱动 jar 就能跑。对那些还在补 Java 基础、连 Maven 依赖都还没搞明白的同学,这种项目反而更友好。它让你把注意力放在 Swing 事件和 JDBC 语句上,而不是跟一堆 XML 配置搏斗。
2.2 拿到压缩包后的标准导入流程:从解压到跑起来的四步
我按自己平时复核课设项目的顺序,给你一套标准导入流程。第 1 步,把压缩包解压到一个没有中文和空格的路径下,比如 D:/inventory。这个细节非常重要,路径里只要出现中文空格,后面配置 classpath 或者数据库 URL 都可能出现玄学问题,报错又怪不到路径上,排查起来非常费时。
第 2 步,确认 MySQL 服务已经启动。如果你装的是 MySQL 8.0,Windows 上通常会出现一个名为 mysql80 的系统服务。用管理员身份打开命令行,执行下面两条命令去确认:
net start mysql80 mysql -uroot -p第一条命令是启动 MySQL 服务,如果服务本来就开着,会提示“请求的服务已经启动”。第二条是登录 MySQL,输入安装时设置的 root 密码。这一步的意义在于:先确认数据库真的能连上,再把锅甩给 Java 代码。很多同学报“连接失败”,其实根本不是代码问题,而是服务没启动。服务名不一定叫 mysql80,有的版本叫 MySQL80,也有自定义的,不确定时用 sc query 查看:
sc query | findstr /i mysql看到服务名之后,用对应的名字启动即可。
第 3 步,用 IDEA 打开项目。打开时直接选择解压后的根目录,IDEA 会根据里面的 .iml 文件和 src 目录识别出这是一个 Java 项目。打开后先做一件事:进入 File -> Project Structure,把 Project SDK 选成本机安装的 JDK,通常选 1.8 或 11 都可以。如果代码里有用到新语法,再考虑更高版本。确认无误后,把 MySQL 驱动 jar 放到 lib 目录下,或者通过 Project Structure 里的 Libraries 手动添加。
第 4 步是导入数据库脚本。资源里的 commodity.sql 建好了库存系统需要的表和初始数据。导入方式多种多样,我最推荐命令行,因为错误信息最直观。假设你已经创建好了一个名为 inventory 的数据库,导入命令如下:
mysql -uroot -p inventory < D:/inventory/commodity.sql没有提前建库的话,先登录 MySQL,执行建库再导入。注意字符集一定要显式指定 utf8mb4:
CREATE DATABASE inventory DEFAULT CHARACTER SET utf8mb4; USE inventory; SOURCE D:/inventory/commodity.sql;这段 SQL 先建数据库,再切换到目标库,最后用 SOURCE 命令执行脚本。为什么用 utf8mb4 而不是 utf8?因为 utf8mb4 是 utf8 的超集,能正确存储中文、表情符号和一些特殊字符。很多老项目中文乱码,就是因为建库时默认用了 latin1,字段再怎么写 utf8 都没用。
导入完成后,执行一个查询,看看数据是否真的进去了:
SELECT id, name, stock FROM goods LIMIT 5;如果能返回商品记录,说明表结构和初始化数据都正常。如果返回 Empty set,先别急着改 Java 代码,回头查两件事:导入时是否切换到正确的数据库,SQL 文件里是否带了 USE 语句把库切走了。很多同学在 Navicat 里导入成功,结果打开 Java 程序依然报“表不存在”,多半就是脚本执行到了别的库。
到这里,环境准备就做完了。我建议你在这一步多花十分钟做一件事:把源码里的数据库连接串打开看一眼,确认库名、用户名、密码和本机配置一致。不要急着运行,先看再跑,能省掉后面一半的报错。
3. 数据库脚本 commodity.sql:库存表结构与登录数据
3.1 先看表结构:商品、库存、登录三张表的关联
拿到 commodity.sql,第一件事不是双击运行,而是先打开看表结构。很多同学把导入脚本当成“一键完成”的黑匣子,全自动灌入之后就再也不管了,直到答辩时被老师问“你这几张表怎么关联的”,才支支吾吾。为了避免这种尴尬,建议你从脚本里提取出核心表,理解每一张表存在的理由。
按这类课设的常见设计,里面至少会有三张关键表:用户表 user、商品表 goods、库存流水表 stock_log。用户表管登录,商品表存商品名称、价格、库存数量,库存流水表记录每次入库出库的明细。三张表通过外键关联起来,商品表的主键 id 被库存流水表的 goods_id 引用。典型的建表语句长这样:
CREATE TABLE `user` ( `id` INT PRIMARY KEY AUTO_INCREMENT, `username` VARCHAR(30) NOT NULL UNIQUE, `password` VARCHAR(50) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; CREATE TABLE `goods` ( `id` INT PRIMARY KEY AUTO_INCREMENT, `name` VARCHAR(100) NOT NULL, `spec` VARCHAR(50), `price` DECIMAL(10,2), `stock` INT DEFAULT 0, `min_stock` INT DEFAULT 10 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; CREATE TABLE `stock_log` ( `id` INT PRIMARY KEY AUTO_INCREMENT, `goods_id` INT, `change_count` INT, `log_time` DATETIME, FOREIGN KEY (`goods_id`) REFERENCES `goods`(`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;我把表结构拆开说明一下。user 表里 username 设置了 UNIQUE 约束,这是为了防止同一账号重复注册,也方便登录时精确匹配。password 字段用的是 VARCHAR(50),课设阶段明文存储就够了,不需要刻意去做加密。goods 表里 price 用 DECIMAL(10,2) 而不是 DOUBLE,是因为浮点数在运算时会产生精度误差,比如 0.1 加 0.2 不等于 0.3,DECIMAL 可以直接避免这个坑。stock 字段保存当前库存数量,min_stock 字段是给“最低库存预警”预留的,这个字段在后面的进阶功能里会很有用。
stock_log 表是典型的流水表,每一条记录表示一次库存变动。change_count 正数表示入库,负数表示出库,log_time 记录操作时间。通过 goods_id 外键和 goods 表关联,查询时把两张表 JOIN 起来,就能得到“某商品最近这段时间的出入库情况”。答辩时如果老师问“库存变动你怎么追踪”,你指一下这张表就行。
为什么强调用 InnoDB 引擎?InnoDB 支持外键和事务,MyISAM 更老但两者都不支持事务。课设里的“入库出库”操作往往要同时更新 goods 表的 stock 字段和 stock_log 表,没有事务的话,两步操作之间只要一步失败,数据就对不上。如果你在答辩时主动提一句“我用 InnoDB 是为了保证事务一致性”,会比单纯描述功能更扎实。
当然,实际下载到的脚本不一定跟我上面写的一模一样,字段名可能叫 product 而不是 goods,也可能没有 stock_log 表。但核心思路一致:用户账号、商品信息、库存记录,三者凑齐,就是一个完整的库存管理系统。你花半小时把脚本里的表名和字段名记在纸上,后面看 Java 代码会轻松很多。
3.2 导入脚本与初始化数据
导入脚本的具体命令在第 2 章已经给过,这里重点说导入之后怎么验证,以及常见的坑。数据导入完成,第一件事是查用户表:
SELECT * FROM user;正常情况下会看到一条 admin 账号记录,密码有可能也是 admin。这个账号就是资源说明里提到的“登录的账号密码”。如果查询结果为空,说明脚本在导入时跳过了这条 INSERT,或者建表成功但没有插入初始数据。这时候手动补一条:
INSERT INTO `user` (`username`, `password`) VALUES ('admin', 'admin');插入后再次查询,确认记录存在。注意,如果 Java 代码里的连接库名不是 inventory,而是别的名字,你需要把表和插入语句全部迁移过去,最稳妥的办法是修改 Java 代码里的连接串,让代码指向你实际导入数据的库。
初始化数据验证完后,再检查一下商品表和流水表的关系是否正常。执行一条多表关联查询:
SELECT g.name, s.change_count, s.log_time FROM stock_log s LEFT JOIN goods g ON s.goods_id = g.id ORDER BY s.log_time DESC LIMIT 10;这条 SQL 的作用是把 stock_log 表和 goods 表关联起来,按时间倒序看最近 10 条库存流水。如果查询报“Unknown column”错误,说明字段名对不上,去核对 sql 脚本里两张表的实际字段名,以实际为准。LEFT JOIN 在这里保证即使某条流水对应的商品被删了,也能显示流水记录,只是商品名称会变成 NULL,这样查出来的记录始终不会减少。
如果你习惯用 Navicat 这种图形化客户端,也有需要注意的地方。右键点击数据库名,选择“运行 SQL 文件”,再选中 commodity.sql。在点“开始”之前,注意看窗口上的“当前数据库”是不是你要导入的目标库。有些版本的 Navicat 会在脚本里没有 USE 语句时,把表建在当前选中的数据库上。如果导完之后发现表出现在别的库,不要慌,重新选对库再导一次即可。
还有一种常见报错是导入时提示语法错误,但脚本在别人机器上明明没问题。这八成是编码问题。SQL 文件可能是 GBK 编码,而你的 MySQL 命令行默认按 UTF-8 解释,中文字符串就变成了乱码,MySQL 不认识乱码里的引号,自然报语法错误。解决办法是在导入命令前面显式指定字符集:
mysql -uroot -p --default-character-set=utf8mb4 inventory < commodity.sql如果指定之后还是报错,就把 commit.sql 用文本编辑器另存为 UTF-8 格式,再执行一次。这个编码坑几乎每个课设季都会出现,我一般拿到任何 sql 脚本,都会先做一步:把文件打开,去看中文注释是否显示正常。显示的是乱码,先另存再导入,不然后面全是冤枉路。
导入成功后,建议你顺手做一次“SQL 和 Java 代码的字段名核对”。打开项目源码,搜索 SELECT 语句,把 Java 里用到的表名和字段名与脚本里的建表语句逐一比对。比如 Java 代码里写的是 SELECT * FROM goods,但脚本里表名是 product,那登录成功后商品列表必然报错。这种问题不在环境配置,单纯是版本迭代留下的坑,提前核对能省掉答辩前的慌乱。
4. 登录模块与主界面:账号密码从哪里来
4.1 登录校验逻辑与界面事件
登录模块是课设答辩时老师几乎必看的部分,因为它涵盖了 Swing 事件处理和 JDBC 两条主线。界面本身不复杂:两个 JLabel、一个 JTextField、一个 JTextField 或 JPasswordField、一个登录按钮。按钮注册 ActionListener,点击后触发 actionPerformed 方法,在这个方法里取界面输入,再去数据库验证。
我把核心代码简化如下:
btnLogin.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { String username = txtUsername.getText().trim(); String password = new String(txtPassword.getPassword()); try { Connection conn = DriverManager.getConnection( "jdbc:mysql://localhost:3306/inventory?useSSL=false&serverTimezone=Asia/Shanghai", "root", "123456"); PreparedStatement ps = conn.prepareStatement( "SELECT * FROM user WHERE username=? AND password=?"); ps.setString(1, username); ps.setString(2, password); ResultSet rs = ps.executeQuery(); if (rs.next()) { JOptionPane.showMessageDialog(loginFrame, "登录成功"); new MainFrame().setVisible(true); loginFrame.dispose(); } else { JOptionPane.showMessageDialog(loginFrame, "用户名或密码错误"); } rs.close(); ps.close(); conn.close(); } catch (SQLException ex) { ex.printStackTrace(); } } });先说逻辑。txtUsername.getText().trim() 会去掉用户名首尾空格,防止手滑多按一个空格导致匹配失败。new String(txtPassword.getPassword()) 是为了拿到密码框里的真实内容,JPasswordField 的 getPassword 返回的是 char 数组,直接 toString 拿不到明文。这里用 PreparedStatement 做参数化查询,比字符串拼接 SQL 安全得多,能避免 SQL 注入。课设阶段虽然不太会真的被攻击,但老师问到“为什么不用 Statement”时,你能答出“预防拼接注入”,印象分会明显不一样。
再看连接串参数。localhost 表示本机地址,3306 是 MySQL 默认端口,inventory 是数据库名,必须和实际库名完全一致。useSSL=false 是关掉 SSL 握手的警告,serverTimezone=Asia/Shanghai 是给 MySQL 8.x 指定时区,这两个参数不写,控制台会刷一堆警告,虽然不影响运行,但答辩时显得不干净。root 和 123456 是你本机 MySQL 的用户名和密码,记得替换成自己的。
有一点要提醒:很多课设项目的连接串不是写在登录按钮里,而是单独抽了一个 DBHelper 类。如果你看到代码里有 DBHelper.getConnection() 这样的调用,那连接串大概率集中在这个类里,后面改密码会方便很多。登录成功后 new MainFrame().setVisible(true) 打开主界面,loginFrame.dispose() 销毁登录窗口,这一步目的是避免关掉主界面后,登录窗口还在后台占着内存。
4.2 修改默认账号密码与重连数据库
资源里提到的“登录的账号密码”,一般会写在课设报告或者脚本注释里。常见的初始值是 admin / admin。如果你运行之后能直接登录,那说明脚本里的数据和代码里的连接串是匹配的。如果登录失败,不要一上来就怀疑代码,先分两步排查。
第一步,确认数据库里的账号密码对不对。登录 MySQL,查询 user 表:
SELECT * FROM user;看到记录后,检查 username 和 password 是否与你输入的一致。如果想改成自定义密码,直接用 UPDATE 语句:
UPDATE user SET password='2024newpass' WHERE username='admin';执行完这条,再重新运行程序,用新密码登录。注意,如果 Java 代码里对密码做了 MD5 或 SHA 加密,那么直接 UPDATE 明文是没有用的,代码会把输入加密后再去比对,你必须把数据库里的值改成加密后的结果。判断代码有没有加密,搜索一下源码里有没有 MessageDigest 或者 DigestUtils 之类的关键词即可。
第二步,确认 Java 代码里的连接参数。打开 DBHelper 类,你会看到类似下面的代码:
public class DBHelper { private static final String URL = "jdbc:mysql://localhost:3306/inventory?useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=utf8"; private static final String USER = "root"; private static final String PASSWORD = "123456"; public static Connection getConnection() throws SQLException { return DriverManager.getConnection(URL, USER, PASSWORD); } }把 USER 和 PASSWORD 改成你本机 MySQL 的实际账号密码。尽量把连接参数集中在一个类里,这是课设代码应该有的习惯。如果项目里把连接串写在了每个界面类中,登录页面一份、商品管理一份、入库出库一份,那改起来非常容易漏。漏掉的后果通常是:登录成功了,但主界面加载数据时报错,或者某个窗口能打开但列表是空的。
另外,资源里可能已经打包好了 mysql-connector-java 的 jar,也可能需要你自己下载。不管哪种,都要确保这个 jar 在 IDEA 的 Project Structure -> Libraries 里存在。如果你在命令行里运行,还要让 classpath 包含这个 jar。这一点经常被忽略,导致在 IDEA 里跑得好好的,一换到命令行就 ClassNotFoundException。
如果你在导入脚本时用了自己创建的数据库名,比如叫 stock_db,而不是 inventory,那就要把上面 URL 路径里的 inventory 改成 stock_db。数据库名不一致的报错很典型:登录时始终提示“用户名或密码错误”,因为 SQL 里的 user 表根本不在当前库里。这时候控制台通常会打印 Unknown database 或者 Table doesn't exist,仔细看堆栈信息就能定位。
5. 避坑/常见问题:课设跑不通的五个真实翻车点
5.1 现象:MySQL 连接报 Communications link failure
报错长这样:Communications link failure,The last packet sent successfully to the server was 0 milliseconds ago. 看到这个,第一反应不是代码问题,而是连不上 MySQL 服务。原因通常有三个:MySQL 服务没启动、端口被占用、URL 里的 host 不对。
解决时按顺序排查。先看服务是否启动,Windows 下用命令:
net start mysql80如果提示服务无法启动,打开 Windows 服务管理器,找到 MySQL 相关服务,右键查看依赖项有没有都启动。然后测试端口通不通:
telnet 127.0.0.1 3306如果你机器上没开 telnet,也可以把 URL 里的 localhost 改成 127.0.0.1 试试,有些极端情况下 localhost 被解析成 IPv6 的 ::1,MySQL 没监听 IPv6 就会失败。如果端口通,继续看 URL 里的端口号是不是 3306,有没有不小心把端口写成 3307。最常见的翻车场景是装了 XAMPP 或者 phpStudy,MySQL 端口被改成了 3307,而代码里还写着 3306。
还有检查一下防火墙,虽然本机访问一般不涉及,但有些安全软件会拦截 Java 进程的对外连接。我处理过一例,代码和数据库全都没问题,最后发现是系统防火墙把 mysql.exe 禁用了,导致外部连接全部超时。这个概率不高,但阻塞很久才排查到。
5.2 现象:ClassNotFoundException: com.mysql.jdbc.Driver
这个异常的意思是 MySQL 驱动类加载不到。原因有两个方向:一是驱动 jar 确实没有加入到项目依赖,二是驱动类名写错了。老版本 MySQL 驱动的类名是 com.mysql.jdbc.Driver,从 MySQL Connector/J 8.x 开始,官方推荐用 com.mysql.cj.jdbc.Driver。资源代码如果是从旧教程抄的,用到新驱动时就会找不到类。
解决驱动类名找不到,最直接的做法是看看你的 jar 包版本。如果使用的是 mysql-connector-java-8.0.x,把代码里所有 Class.forName("com.mysql.jdbc.Driver") 改成 Class.forName("com.mysql.cj.jdbc.Driver")。如果懒得改代码,也可以去找 5.1.x 版本的旧驱动,但我不推荐,因为 MySQL 8.0 的默认认证插件是 caching_sha2_password,旧驱动不支持,即使类加载成功,登录时也会报认证错误。相比改类名,把立桩码里的驱动类名统一改成新版,再同步引入对应版本的 jar,是最稳的路径。
IDEA 里添加 jar 的操作是:File -> Project Structure -> Libraries -> 加号 -> Java,选择你的 mysql-connector-java jar 文件。加完之后,确认它出现在 Modules 的 Dependencies 里,而且没有被排除掉。有些同学把 jar 手动拷贝进 src 文件夹里,以为这样就“导入”了,其实 IDEt 不会自动把 src 下的 jar 加入编译指针,必须在 Project Structure 里显式添加才生效。
5.3 现象:登录界面输入中文后变成问号或乱码
中文乱码是课设项目最常见的表现,具体是数据库里存进去的中文变成“?”,或者在界面上显示成了乱码。原因通常出现在三个层面:数据库字符集、JDBC 连接串字符集、IDE 的源码文件编码。
第一步,检查数据库和表是否用了 utf8mb4。你可以在 MySQL 里执行:
SHOW CREATE TABLE goods;建表语句里如果没有 DEFAULT CHARSET=utf8mb4,说明建库时没指定字符集。处理办法是重新创建库,或者用 ALTER TABLE 转换:
ALTER TABLE goods CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;第二步,检查连接串有没有加 characterEncoding 参数:
jdbc:mysql://localhost:3306/inventory?useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=utf8这个参数告诉 MySQL 客户端按 UTF-8 编码发送和接收数据。如果少了它,连接默认会用服务器端字符集,一旦服务器是 latin1,中文传输过程就丢失了。
第三步,也是最容易被忽略的:IDEA 的文件编码。进入 File -> Settings -> Editor -> File Encodings,把 Global Encoding、Project Encoding、Properties Files 全部设为 UTF-8。很多同学的代码文件本身是 GBK 编码存盘的,IDEA 用 UTF-8 打开以后,源码里所有中文字符串常量都是乱码,这种乱码和数据库没有任何关系。看清文件的右下角,如果显示的是 GBK,就转换成 UTF-8 再重新编译。
5.4 现象:运行主类后窗口一闪而过直接退出
有些同学喜欢直接双击运行生成的 jar 包,结果窗口一闪就没了。这个现象本质是 JVM 在执行主线程时抛出了未捕获异常,程序直接终止。常见原因有两个:数据库连接失败,或者主方法里写了 System.exit() 但前面的初始化代码没有兜底。
解决的第一步,别用双击运行,先回到 IDEA 里点绿色运行按钮。IDEA 的控制台会保留堆栈信息,你一眼就能看出异常抛在哪个环节。如果是 SQLException,按 5.1 和 5.2 排查。如果是 FileNotFoundException,看看代码里读的文件路径是不是写死了绝对路径,比如 D://temp/data.txt,一旦目录不存在就会崩。
还有一个更隐蔽的原因:代码里的静态代码块加载驱动失败。比如:
static { try { Class.forName("com.mysql.cj.jdbc.Driver"); } catch (ClassNotFoundException e) { e.printStackTrace(); } }如果驱动 jar 没加到依赖里,这里的异常被 e.printStackTrace() 接住,程序并不会崩,但后面 getConnection 时因为没有驱动注册,可能会报 No suitable driver。如果你看到的是一闪而过,多半是异常没有被 catch,直接向外抛出了。排查时可以先在 main 方法最外层加一个 try-catch(Exception e) 打印完整堆栈,就能把隐藏的异常揪出来。拿到源码后,我都会建议同学先加这一层保护再运行,不是代码不行,而是交付环境和自己的环境经常有差异,多一层输出比干瞪眼强。
5.5 现象:课设报告和源代码对不上,答辩时被老师问住
这个坑不发生在运行阶段,而是发生在答辩现场。资源包里有一份 docx 课设报告,报告里的功能模块图写的是一套,源代码里类名的包路径是另一套;报告里贴的数据库设计表和 commodity.sql 里的实际字段不一样。这种情况在接单交付的源码里经常出现,因为项目改过多轮,报告却没同步更新。
解决办法是在答辩前做一次完整的一致性核对。打开报告,找到“系统功能结构图”,然后把源码中 src 目录下的包名和类名列出来,逐项对照。比如报告写“包括登录模块、商品添加、商品修改、入库出库、查询统计”,你就要在代码里找到对应的 MainFrame、LoginFrame、GoodsManager 等类,确认每个功能点都在代码里有入口。
数据库设计部分单独核对。报告里的表格列出字段名、类型、说明,你打开 commodity.sql 建表语句,逐字段比对。不一致的地方,优先改代码让它去适配脚本,因为脚本已经导入数据库了,改脚本重新导数据反而费时间。改完代码后,把报告里的字段说明也跟着改一下,保持文档和代码一致。如果老师翻报告问“这个字段为什么存在”,你至少能指着代码说出它的作用。报告不要求完美,但要求自洽,这是一条最实在的答辩经验。
6. 进阶:给库存系统加一个低库存预警与 CSV 导出
6.1 用 Swing Timer 做低库存轮询
课设做成基本功能后,想加分可以加一个低库存预警。Swing 里的 Timer 可以定时执行一个动作,正好用来做库存轮询。代码很短:
Timer timer = new Timer(5000, e -> { int lowCount = DBHelper.countLowStock(); if (lowCount > 0) { statusLabel.setText("当前有 " + lowCount + " 种商品低库存"); } }); timer.start();这段代码每 5 秒查一次数据库,统计 stock 小于 min_stock 的商品种类数,然后更新到主界面的状态栏。注意 Timer 的回调是跑在事件分发线程里的,直接改界面不会报并发错误。countLowStock 方法里的 SQL 大致是:
SELECT COUNT(*) FROM goods WHERE stock < min_stock;5000 是毫秒数,课设演示时可以设短一点,效果明显;实际使用设 30000 更合理,避免频繁访问数据库。这个功能会用到上次建表时预留的 min_stock 字段,正好能讲一句“我在设计表时就想到了预警需求”,逻辑闭环。
6.2 把 JTable 数据导出为 CSV
另一个容易讲清楚的进阶功能是把库存列表导出成 CSV 文件。用 java.io 的 BufferedWriter 就能实现,不依赖第三方库:
try (BufferedWriter writer = Files.newBufferedWriter(Paths.get("inventory.csv"))) { writer.write("商品名,库存,最低库存"); writer.newLine(); for (int i = 0; i < table.getRowCount(); i++) { writer.write(table.getValueAt(i, 1) + "," + table.getValueAt(i, 3) + "," + table.getValueAt(i, 4)); writer.newLine(); } }这段代码从 JTable 里按行取当前界面展示的数据,写入 CSV 文件。导出功能的加分点在于:你能主动讲到 JTable 的 getValueAt 是按行列取值,课堂上刚好讲过,老师不会觉得超纲。需要注意 CSV 文件的内容如果含中文,用 Excel 打开可能乱码,原因是 Excel 默认用 ANSI 编码读取。
当初我验收课设项目时,最在意的不是功能数量,而是每个功能你能否从界面触发说到数据库语句。低库存预警和 CSV 导出这两个扩展点,正好覆盖了 Swing Timer 和文件流两个知识点,放到答辩时主动讲出来,很容易把老师往你熟悉的领域引导。我自己每次拿到这类带数据库的课设源码,都会先看有没有 min_stock 这类预留字段,有的话说明作者留了扩展空间,加这些功能会顺手很多。从那以后,我做课设也习惯先想清楚哪个字段能支撑附加功能,再动手写界面。希望这套拆解思路帮到你。
本文还有配套的精品资源,点击获取