简介:这是一份基于Java Swing与MySQL的学生选课系统项目源码包,适合Java初学者、课程设计及毕业设计参考。系统实现了课程查询、选课、退课、成绩查看、密码修改等基础功能,界面采用Swing构建,数据库使用MySQL,配套文档和视频能帮助快速上手。包体共168个文件,包含23个Java源码、63个编译后的class文件、24个form界面设计文件、SQL数据库脚本、avi演示录像,以及docx/doc说明文档,整体约58.87MB。其中png图片、jar依赖库等为运行和界面资源,结构清晰,导入Eclipse或MyEclipse即可运行调试。包内另有数据库文件(db)和配置文件(classpath、project、prefs),方便还原环境。已有861人学习下载,适合需要完整项目实现过程、数据库配置讲解及Swing界面布局参考的读者,可作为选题模板或功能扩展基础。
1. 学生选课系统源码包:Java Swing与MySQL的组合到底能做什么
学生选课系统是Java毕业设计里出现频率极高的题目,网上源码包很多,但真正能一次跑起来的并不多。这套Java Swing + MySQL实现的学生选课系统项目源码,自带文档和演示视频,压缩包里是完整的工程文件,从登录、课程管理到学生选课、已选课查询和密码修改,闭环齐全。适合两类人:一是正在做毕业设计、需要一套可改可扩展的桌面程序打底的同学,二是刚学完Java基础、想看看Swing怎么和数据库做真实交互的入门者。它能帮你省下的,不是写代码的时间,而是从零搭窗体、调布局、设计DAO层这些重复劳动。
2. 导入Eclipse前的项目体检:编码、JDK与构建路径的排查顺序
先说一个容易被忽视的事实:解压源码包后,你看到的不只是.java源文件,还有一批.class文件,比如CourseManageInterFrm.class、LogOnFrm.class、MainFrm_admin.class。这些是上一台机器编译过的产物,目录里混着它们会干扰判断,而且不同JDK版本编译出来的class文件不一定兼容。我拿到任何Swing源码包,第一件事不是双击打开工程,而是按顺序做体检,否则后面报错你根本分不清是代码问题还是环境问题。
2.1 源码结构:先分清.class、.java与lib目录
在正式导入前,用解压工具把zip包解开,在文件管理器里把目录结构过一遍。常见的学生选课系统工程是这种形态:src目录下放着若干.java文件,包名按功能区分,登录、课程管理、选课、密码修改各自成文件;项目根目录下有.classpath和.project文件;lib目录里放MySQL的JDBC驱动jar包。如果jar包不在lib里,导入之后还得手动加构建路径,这一步忘了,后面运行必报ClassNotFoundException。
.class文件是和.java一一对应的编译产物。比如StudentPasswordInterFrm.class对应学生修改密码的窗体,PasswordModifyInterFrm.class对应另一个密码操作窗体。为什么不直接删掉.class?可以删,但删之前建议先备份一份到项目外。它有一个用处:当你把.java改乱了、编译不通过时,可以用备份的.class临时比对行为,或者用反编译工具看原来的实现。删掉.class之后,Eclipse会在保存.java时自动重新编译,不用手动管。
lib目录里的jar包则要单独检查。最关键的jar是mysql-connector-java,版本要和本机MySQL匹配:MySQL 5.x时代用5.1.x的驱动,MySQL 8.x要用8.0.x的驱动,否则连接阶段会报SSL或驱动类找不到。如果解压后没看到lib目录,就直接看源码里import了哪些包,搜索java.sql.*和com.mysql,确认驱动引入路径。
2.2 导入后的三个必改配置:编码、JDK与编译级别
把整个项目文件夹复制到Eclipse工作区之后,用File -> Import -> Existing Projects into Workspace导入。导入后如果项目名上带黄色感叹号,说明编译环境有问题。按下面顺序处理,顺序不要反,反了经常会白忙一场。
第一步处理编码。右键项目 -> Properties -> Resource,看Text file encoding。Swing毕业设计源码大量使用中文注释,如果项目原来是GBK编码,而你机器上Eclipse默认UTF-8,注释会变成乱码,甚至把字符串字面量里的中文也搞乱,导致界面显示"锟斤拷"之类的字符。判断标准很简单:打开一个.java文件看中文注释正不正常,乱码就把编码从UTF-8切到GBK,或者反过来,切到注释正常为止。
第二步处理JDK。右键项目 -> Properties -> Java Build Path,在Libraries页签找到JRE System Library,Remove掉,再点Add Library -> JRE System Library,选本机安装的JDK。这里有个常见翻车点:项目要求JDK 8,本机装的是JDK 17,强行用17编译老代码,个别语法会报错。最省事的做法是装一个JDK 8,在Eclipse的Installed JREs里把多个版本都登记上,按项目需求切换。
第三步处理编译级别。右键项目 -> Properties -> Java Compiler,勾选Enable project specific settings,把Compiler compliance level设成1.8。这个值不是越高越好,高版本编译特性在老JDK运行时环境里会报UnsupportedClassVersionError。设完三项之后,右键项目 -> Clean,让Eclipse全量重新编译一遍。
提示:Clean之后如果还有红叉,就展开Problems视图看具体报错文件,十有八九是jar包缺失或者某个源码文件编码损坏。
2.3 确认驱动在构建路径里:用这四条验证
改完上面三步,项目还出现红叉,就重点看Referenced Libraries里有没有MySQL驱动。展开项目名 -> Referenced Libraries,如果没有mysql-connector-java.jar,右键项目 -> Build Path -> Configure Build Path -> Libraries -> Add External JARs,手动指定jar位置。顺便说一句,这个工程的.sql文件和项目文件是分开的,数据库脚本要单独导入MySQL,这一步不完成,程序就算编译通过,一运行也照样报连接失败。
3. 数据库还原与连接配置:Navicat导入SQL脚本的四个关键参数
后台数据库是MySQL。学生选课系统的所有业务数据都落在三张核心表上:学生表、课程表、选课关系表。选课关系表存的是学号和课程号的对应关系,是选课系统里最容易出问题的表。这一章按实操顺序讲,怎么把SQL脚本还原成本机数据库,再让Swing程序顺利连上。
3.1 建库与导入:Navicat执行的完整步骤
用Navicat还原数据库,顺序是:先建连接,再建库,最后运行SQL脚本。新建连接时,host填127.0.0.1,端口填3306,用户名填root,密码填安装MySQL时设置的密码。点测试连接,提示连接成功再继续。
接着右键连接 -> 新建数据库,库名建议按脚本里的建库语句来,常见的是course或者student_course,字符集和排序规则都选utf8mb4。库名很关键,因为Java代码里的url是写死的,如果代码里写的是jdbc:mysql://localhost:3306/course,你建的库名必须叫course,否则后面程序启动时直接报Unknown database。
建好库后,选中这个数据库,右键 -> 运行SQL文件,找到源码包中的.sql文件。执行期间留意右下角的进度条,SQL文件如果包含中文字符,在打开文件那里确认编码格式,脚本本身是UTF-8就选UTF-8,是GBK就选GBK。导入完刷新数据库,展开表列表,能看到导入出来的表结构。
执行完SQL脚本后,建议立刻执行下面几句,确认数据是否完整:
SHOW TABLES; SELECT * FROM student; SELECT * FROM course; SELECT * FROM sc;第一句列出当前库全部表,后三句分别看学生、课程和选课记录。这些表有没有初始数据,直接决定程序登录时能不能验证账号。
提示:如果student表是空的,登录界面输入任何账号都会提示用户不存在。需要手动插入一条测试学生数据,或者去文档里找初始账号。
3.2 连接参数集中配置:DBHelper类与url四个参数
Swing项目的数据库连接通常集中在DBHelper类里完成,少数用properties文件。这套源码以哪种形式为准,打开src目录看一眼就知道。无论是哪种形式,连接参数就四项:
| 参数 | 推荐值 | 说明 |
|---|---|---|
| URL | jdbc:mysql://localhost:3306/course?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai | 库名必须和导入的库名一致 |
| 驱动类 | com.mysql.cj.jdbc.Driver | MySQL 8推荐;MySQL 5用com.mysql.jdbc.Driver |
| 用户名 | root | 本机账号 |
| 密码 | 安装时设置的密码 | 建议用纯数字或字母,避免特殊字符干扰 |
MySQL版本不同,驱动类名不一样。5.x的驱动类是com.mysql.jdbc.Driver,8.x的驱动类是com.mysql.cj.jdbc.Driver。如果把8.x的驱动配成旧类名,运行时是ClassNotFoundException;反过来把5.x配成新类名一样报错。url末尾的serverTimezone=Asia/Shanghai是给8.x驱动用的,不加会报Server time zone的运行时异常。
如果项目用的是DBHelper.java,打开它修改时注意,老项目习惯把连接信息写死在静态代码块里,修改完保存后必须重新编译,否则跑的仍是旧字节码。如果用的是db.properties,改完文件后重启程序即可。
3.3 数字类型字段的匹配:为什么学号要用字符串存
看表结构时,观察一下student表的sno字段类型。选课系统里学号如果设计成int,会遇到一个问题:学号可以以0开头,例如20230101001这样的长数字,int类型要么截断、要么溢出;而字符串类型不会。所以这个系统把学号存成varchar,看着别扭,实际是合理的。
对应的,sc表里外键关联也用字符串。在Java代码里用getString()取学号,拼接SQL时要小心引号,下面这段是典型的插入写法:
String sql = "INSERT INTO sc(sno, cno) VALUES('" + sno + "', '" + cno + "')";常见做法是学号和课程号都从界面控件的getText()里取,拼SQL前先做一次非空判断,两边都为空时直接return,避免INSERT语句写成了VALUES('', '')这种脏数据。
4. 跑通双角色操作流:管理员、学生与密码修改的验证路径
程序编译通过、数据库还原成功之后,就进入验证环节。这套系统的类名已经暴露了整个操作流:登录、课程管理、学生选课、已选课程、密码修改。按用户身份拆成两条路径分别验证,任何一步卡住,都能快速定位到是界面问题还是SQL问题。
4.1 登录窗体:身份逻辑与初始账号
入口是LogOnFrm.java,运行这个类的main方法会弹出登录窗口。登录逻辑一般是这样:先从输入框获取用户名和密码,再去对应的表里查,查到了就根据用户类型字段决定进入哪个主窗体,查不到就提示账号或密码错误。典型的Java实现里,PreparedStatement比Statement更值得学:
String user = txtUser.getText().trim(); String pwd = new String(txtPwd.getPassword()); String sql = "SELECT * FROM student WHERE sno = ? AND password = ?"; PreparedStatement ps = conn.prepareStatement(sql); ps.setString(1, user); ps.setString(2, pwd); ResultSet rs = ps.executeQuery(); if (rs.next()) { // 进入学生主界面 StudentViewInterFrm } else { JOptionPane.showMessageDialog(this, "用户名或密码错误"); }用PreparedStatement而不是Statement拼SQL,是为了防注入。毕业设计演示时,如果你能在代码里指出这一点并解释为什么不用字符串拼接,答辩老师通常会给加分,这是一个很便宜的亮点。
验证登录时,先故意输错一次密码,确认能弹出错误提示;再用正确账号登录。错误提示正常弹出,说明数据库查询链路是通的;如果登录按钮点了没反应,多半是查询抛了异常被吞掉,去控制台看异常栈。
4.2 管理员端:课程管理与新增的完整链路
管理员登录后进入MainFrm_admin,这是一个主窗体,里面用按钮或菜单挂载课程管理、课程新增等功能。点击课程管理打开CourseManageInterFrm,列表展示现有课程;点击新增打开CourseAddInterFrm,填写课程编号、课名、学分、容量后保存。
这里有一个容易忽略的流程:新增课程后,课程列表不会自动刷新,要手动关闭子窗体再打开,或者在添加成功的代码后面加一条查询重新填充表格数据。如果发现添加后列表不变,别急着怀疑SQL,先看是不是忘了刷新。
课程容量字段建议设置一个合理的默认值,比如40,容量为0的课程学生是选不了的。容量和已选人数的关系,在管理员端最好做一个同步显示,修改容量时先查sc表里该课程已被选了多少人,容量不能低于已选人数,这是数据完整性的一部分。
4.3 学生端:选课、已选课与退课的操作验证
学生登录后进入StudentViewInterFrm,这个窗体通常会提供一个表格展示所有课程,选课按钮触发SelectCourseInterFrm里的插入逻辑。选课时,如果没有先查询该生是否已选这门课,直接执行INSERT,会出现重复选课。正常流程应该是:
- 点击选课按钮;
- 先查sc表有没有这条sno+cno记录;
- 有则提示已经选过,没有则执行INSERT,同时把course表里的已选人数加一。
已选课查询对应SelectedViewInterFrm,学生登录后应该能在这里看到自己的选课列表。如果这个列表是空的,返回去看sc表是否真的插入了记录,有时候插入成功但查询条件写反了,导致查不到。
4.4 密码修改模块:两条路径不要混淆
StudentPasswordInterFrm和PasswordModifyInterFrm这两个类名,刚上手容易以为是同一个东西。功能上,学生自助修改密码需要验证原密码,管理员重置密码则可以直接指定新密码。验证时分别测试两种场景:
// 学生修改密码,必须先校验原密码 String sql = "UPDATE student SET password = ? WHERE sno = ? AND password = ?"; // 管理员重置密码,直接覆盖 String sql2 = "UPDATE student SET password = ? WHERE sno = ?";第一种SQL如果影响行数为0,说明原密码不对;第二种SQL不受原密码限制。这个区别在答辩时经常被提问,密码修改模块如果实现成了不校验原密码,安全性是不过关的。
5. 学生选课系统避坑实录:五个高发坑与现场处理步骤
把前面讲的运行流程走下来,大部分问题会集中在环境、编码和数据库三个区域。这一章记录五种最常见的故障,每一条都按现象、原因、解决三个层次写,照这个顺序排错,能省下大量试错时间。
5.1 界面中文全部乱码
现象:程序能启动,但窗体标题、按钮文字、课程名称显示成"锟斤拷"或"???",数据库里中文正常。
原因:源码文件是GBK编码,Eclipse用UTF-8打开导致编译后的字符串乱码;或者相反,数据库表的字符集与程序写入时不一致。乱码不一定是一个方向,界面乱码与数据库乱码可能同时存在。
解决:先看数据库里的中文是否正常,正常的话只改Eclipse项目编码。右键项目 -> Properties -> Resource,把Text file encoding从UTF-8改成GBK,Clean后重新运行。如果数据库里的中文也是问号,说明建库时字符集选错了,需要重建成utf8mb4并重新导入SQL。
5.2 点击登录没有任何反应
现象:输入账号密码后点登录,界面不跳转、不报错,像卡住一样。
原因:可能是控制台有异常被吞掉,也可能是数据库连接超时。Swing里按钮点击事件如果抛异常没有用try-catch捕获并打印,用户界面上什么都看不到,程序就停在原地。
解决:先看Eclipse控制台,把堆栈信息贴出来。常见两类堆栈:一类是Connection refused,说明MySQL服务没启动,去系统服务里启动mysql;另一类是Access denied for user,说明账号密码不对,去DBHelper或db.properties里改。排查时也可以在登录按钮事件里临时加一行System.out.println(e.getMessage()),让异常打印到控制台。
5.3 找不到或无法加载主类
现象:右键项目 -> Run As -> Java Application,列表里找不到任何带main方法的类。
原因:常见于.class文件被清理后还没有重新编译,或者项目没有被识别为Java项目。Eclipse对src目录的Source Folder标记丢失后,不会把.java文件纳入编译范围。
解决:先右键项目 -> Properties -> Java Build Path -> Source,确认src目录存在且没有排除标记。再检查项目根目录有没有.project和.classpath,如果手动移动过文件,这两个文件会失效。最稳的修复是重新导入项目:把项目文件夹从工作区删掉,再用Import重新拉进来,让Eclipse重新生成项目元数据,然后Clean。
5.4 删除课程时报外键约束错误
现象:管理员删除一门课程,程序抛出类似Cannot delete or update a parent row的异常,但删除其他课没问题。
原因:该课程已经被学生选过,sc表里有外键记录。直接删course表里的主记录,数据库外键机制会阻止这次删除。
解决:两个方向。一是代码层面,删除前先执行DELETE FROM sc WHERE cno = ?,清掉选课关系,再删除课程;二是数据库层面,把外键改成级联删除。毕业设计项目规模不大,我建议用代码控制,因为同时可以把"该课程已被学生选"的业务提示做进去,比数据库静默删除更合理。
5.5 同一门课被重复选入
现象:学生在短时间内连续点两次选课按钮,sc表出现两条相同sno和cno的记录。
原因:SELECT检查与INSERT之间没有加锁,也没有数据库唯一约束,两次点击都通过了查询判断,各自执行了一次插入。
解决:三条线同时做。代码里,插入前先查一次sc表;界面上,点击后立即setEnabled(false)防止二次提交;数据库里,给sc表加唯一索引。三个层级都做,多终端并发时也不会产生重复记录。表结构修正SQL如下:
ALTER TABLE sc ADD UNIQUE INDEX uk_sno_cno (sno, cno);加了这层约束后,如果再遇到重复插入,数据库会直接报Duplicate entry错误,程序里捕获到这个异常,可以转成一个友好提示,比如"该课程已选过"。
6. 进阶用法:三个让源码价值翻倍的小技巧
项目跑通只是开始。用这套学生选课系统做毕业设计或练手,最好能读出三层东西:表结构设计、登录流程、选课业务的防重方式。下面是三个我觉得性价比最高的技巧。
第一个技巧:用.class文件名反向追踪业务边界。像CourseAddInterFrm和CourseManageInterFrm,一个管新增、一个管管理,命名已经帮你把功能模块标好了。打开对应的.java文件,先看构造方法里new了哪些控件,再看按钮事件绑定在哪个方法上,照着这个顺序读,比看十遍教程管用。老项目的界面代码经常冗长,这种读法能让你快速找到核心逻辑。
第二个技巧:给sc表加唯一索引,作为防重兜底。我之前在一个类似系统里吃过亏,觉得代码里加了判断就万无一失,结果快速双击时还是进去了两条重复记录。从那以后,凡是有外键关系的业务表,我都要在数据库加唯一索引,把最后的兜底责任放在数据库层,代码逻辑失误时数据库还能拦一手。
第三个技巧:把密码明文改成摘要存储。原系统的password字段大概率是明文,你可以写一个MD5或SHA-256工具方法,登录时对输入的密码做哈希后再比对数字摘要,注册或改密时把摘要写进库。这个改动不需要动表结构,只需要在一个工具类里加方法,然后把原来传明文的地方替换掉,面试被问到密码存储时也能讲出你的处理思路。
整个源码包本身的教学价值,比"一个能运行的程序"大。环境配置这关踩过一次,之后再装任何Java老项目,心里都有底。从那以后我每次跑别人给的Java Swing源码,都强制走一遍体检流程:先看编码和构建路径,再还原数据库,最后才运行,并且每步都截图留底。环境问题没有现场,连复现都谈不上,更别说修复了。希望这些经验帮到你,少走几步冤枉路。
本文还有配套的精品资源,点击获取