简介:这是一份基于Java与MySQL的学生成绩管理系统完整项目,面向正在学习Java GUI编程、数据库交互以及软件工程实践的开发者,尤其适合作为课程设计或毕业设计的参考案例。压缩包内共104个文件,包含29个Java源码、68个编译后的class文件,另有两个jar依赖库、项目配置与一份docx说明文档,整体大小仅714KB,结构明了,可直接导入开发环境查看运行,便于按模块阅读和调试。项目覆盖学生信息管理、成绩录入与查询、数据统计分析、选课管理以及用户权限控制等功能模块,从界面布局、事件监听、JDBC连接,到SQL增删改查均有体现,形成完整的业务闭环。已有600人学习下载,对于希望理解图形界面与MySQL后端结合、掌握实际项目分层结构的初学者,这份资源能提供清晰的代码参照和设计思路,帮助快速上手。
1. Java学生成绩管理系统.rar:期末成绩录入为什么需要这样一个Java小系统
Java学生成绩管理系统.rar 这类压缩包,是计算机课程设计里最常见的交付物。期末成绩登记基本靠Excel来回传,轻则格式错乱,重则成绩覆盖,一个学期一次的返工就够让人崩溃。这个Java小系统把学生信息维护、成绩录入、查询统计放进一个工程,解压、导入IDE、配上MySQL就能跑。
适合刚学完Java基础的人,也适合被安排做教学管理原型的一线从业者。不过拿到包先别急着双击运行,先认清它是Web项目还是桌面程序,这两种形态的导入、启动和排错路径完全不同。花两分钟确认结构,能省掉一整晚的环境问题。
2. 把.rar变回可运行工程:JDK版本检查与IDE导入步骤
2.1 解压前先看包结构:源码、SQL脚本和说明文档
先从解压说起。拿到Java学生成绩管理系统.rar,在Windows上我一般用WinRAR双击解压,在Linux或macOS上用unrar命令行:
# 安装unrar后执行 unrar x Java学生成绩管理系统.rar -d ./student-score-system/参数里,x表示保留压缩包内完整目录结构并解压,-d指定输出目录。这一步别直接在压缩包窗口里双击找文件,那样临时文件和解压内容混在一起,容易把项目路径搞乱。
解压完先别急着打开IDE,花两分钟把目录结构看一遍,判断这个包是什么形态。我见过两种最常见的布局:
student-score-system/ ├── src/ # Java源码 │ └── com/example/ │ ├── entity/ # 实体类(Student、Score) │ ├── dao/ # 数据访问层 │ ├── servlet/ # Web控制层 │ └── util/ # 数据库连接工具类 ├── web/ # Web根目录 │ ├── WEB-INF/ │ │ ├── web.xml │ │ └── classes/ │ └── login.jsp ├── sql/ │ └── init.sql # 建库建表脚本 └── README.md # 项目说明如果看到src下有Main.java而web目录不存在,那是Swing或JavaFX桌面程序;有web/WEB-INF和web.xml,就是Servlet/JSP的Web应用。Java学生成绩管理系统.rar里最常见的是Web形态,课程设计通常要求B/S架构,老师用浏览器访问就行,不用每台机器都装客户端。
接下来看README.md,里面通常会写死三件事:JDK版本、MySQL版本、Tomcat版本。这三个版本对能不能一次跑通影响最大。有的包README写得很随意,只留一句"用IDEA打开即可",这时候就要靠下一步的环境检查兜底。
2.2 JDK与IDE版本匹配:避免一导入就报错
Java版本不匹配是导入期的第一大坑。老项目用JDK 8编译,新电脑装了JDK 17或21,一打开不一定立刻报错,最怕的是运行到中途抛UnsupportedClassVersionError。命令行先确认当前环境:
# 查看当前Java版本 java -version javac -version如果输出带1.8.0_,那就是JDK 8;如果是17.0.x或21.0.x,要注意项目是否依赖只在JDK 8下存在的内部API。常见做法是:装一个JDK 8,在IDE里给这个项目单独指定Project SDK为8,而不是动全局环境变量。IDEA里File -> Project Structure -> Project SDK,下拉换成8,再把Language Level设成8。
这里多说一句java环境配置的问题,也是经典痛点:机器上装了多个JDK,环境变量JAVA_HOME指来指去,命令行java -version和IDE里用的不是同一个。我处理这类压缩包的习惯是:不依赖系统JAVA_HOME,在IDE里给Project SDK指定绝对路径,比如C:\Program Files\Java\jdk1.8.0_202,这样系统环境变量乱不乱都不影响项目本身。
2.3 IDEA导入Web工程与桌面工程的标准操作
确认JDK后,用IDEA导入。Web版的步骤是:
- File -> New -> Project from Existing Sources
- 选中解压后的根目录,如果有pom.xml就选pom.xml,否则直接选根目录
- 把src目录标记为Sources Root,web目录标记为Web Resources
- Run -> Edit Configurations -> Add New -> Tomcat Server -> Local
- 在Deployment页签里加上Artifact,Application context填项目名就行
Eclipse则简单一些:File -> Import -> Existing Projects into Workspace,选根目录,Eclipse会读取.classpath和.project文件自动识别工程。
如果是Maven工程,压缩包里会有pom.xml,IDEA识别后会把依赖全部拉下来,最省事。但很多课程设计不用Maven,而是把mysql-connector-java.jar直接放在lib目录下手动管理。这种情况下,IDEA里需要右键lib目录 -> Add as Library,把jar加进依赖。这个动作漏掉的话,编译能过但运行时会报ClassNotFoundException: com.mysql.cj.jdbc.Driver。
桌面版导入更简单,IDEA直接Open项目根目录,如果源码目录结构清晰,右键Main类就能Run。需要额外注意的是桌面版通常要把lib/下的驱动jar也Add as Library。这一步做完,项目才能在编译期和运行期同时找到JDBC驱动类。
3. 核心代码走读:两张表、实体类与增删改查怎么做
3.1 建表SQL:student与score的主外键关系
打开sql/init.sql,最核心的是两张表:student(学生)和score(成绩)。典型的建表语句是:
CREATE DATABASE IF NOT EXISTS student_db DEFAULT CHARSET utf8mb4; USE student_db; CREATE TABLE student ( id INT PRIMARY KEY AUTO_INCREMENT, student_no VARCHAR(20) NOT NULL UNIQUE COMMENT '学号', student_name VARCHAR(50) NOT NULL COMMENT '姓名', class_name VARCHAR(50) COMMENT '班级', create_time DATETIME DEFAULT CURRENT_TIMESTAMP ) ENGINE=InnoDB COMMENT='学生表'; CREATE TABLE score ( id INT PRIMARY KEY AUTO_INCREMENT, student_id INT NOT NULL, course_name VARCHAR(50) NOT NULL COMMENT '课程名称', score DECIMAL(5,2) NOT NULL COMMENT '成绩', exam_time DATE COMMENT '考试日期', FOREIGN KEY (student_id) REFERENCES student(id) ) ENGINE=InnoDB COMMENT='成绩表';字段设计上需要注意:student_no加了UNIQUE约束,防止同一个学号录入两次;score表用student_id做外键,而不是直接存学号字符串,这是第三范式的考虑——学生表里修改姓名后,成绩表不需要跟着改。DECIMAL(5,2)表示最长5位数字、保留2位小数,99.99这样的分值都能存,比FLOAT更适合存成绩,浮点类型算平均分时会出现精度漂移。
很多新手喜欢把学生姓名直接冗余到score表,查询确实少一个JOIN,但代价是学生改名的场景要同步改两处,这是典型的更新异常。这段关系建模,几乎是java面试题里数据一致性问题的常客,建议按主外键设计走。
3.2 实体类与DAO:Java数据类型映射到MySQL字段
对应上面的建表SQL,entity包里的Student.java和Score.java核心字段如下:
// Student.java 实体类 public class Student { private Integer id; // 对应数据库id INT private String studentNo; // 对应student_no VARCHAR private String studentName; // 对应student_name VARCHAR private String className; // 对应class_name VARCHAR // getter/setter用IDE自动生成 }学生表四个字段用Integer和String对应INT和VARCHAR,这是Java数据类型与MySQL字段最直接的映射。成绩表注意一点:DECIMAL在Java侧用BigDecimal或Double接收,不要用Float。Float在累加和求平均时精度损耗明显,这是面向对象编程java里封装基础类型时容易忽略的点。
DAO层写法,几乎是java八股文里手写JDBC的经典片段:
// ScoreDao.java 核心方法 public class ScoreDao { private static final String DRIVER = "com.mysql.cj.jdbc.Driver"; private static final String URL = "jdbc:mysql://localhost:3306/student_db?useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=utf8"; private static final String USER = "root"; private static final String PASSWORD = "123456"; public List<Score> listByStudent(Integer studentId) { String sql = "SELECT * FROM score WHERE student_id = ? ORDER BY course_name"; List<Score> list = new ArrayList<>(); try (Connection conn = DriverManager.getConnection(URL, USER, PASSWORD); PreparedStatement ps = conn.prepareStatement(sql)) { ps.setInt(1, studentId); try (ResultSet rs = ps.executeQuery()) { while (rs.next()) { Score score = new Score(); score.setId(rs.getInt("id")); score.setStudentId(rs.getInt("student_id")); score.setCourseName(rs.getString("course_name")); score.setScore(rs.getBigDecimal("score")); list.add(score); } } } catch (SQLException e) { e.printStackTrace(); } return list; } }参数说明三个关键点:
useSSL=false关闭MySQL 8.x默认的SSL安全连接校验,不关会报SSL握手警告甚至连接失败;serverTimezone=Asia/Shanghai解决驱动和数据库服务器的时区偏差;characterEncoding=utf8让中文不乱码。try-with-resources语法在JDK 7以上可用,能自动关闭Connection、PreparedStatement、ResultSet等资源,比老式手动finally.close更安全,也是现在主流的写法。
3.3 Servlet控制层:成绩录入和查询的请求链路
Web版里控制层通常是三个Servlet:LoginServlet验证账号,StudentServlet管学生信息,ScoreServlet管成绩。以成绩录入为例,请求链路是:
浏览器提交score表单 -> web.xml或@WebServlet注解路由到ScoreServlet -> doPost接收参数 -> 组装Score对象 -> 调用ScoreDao.insert -> 重定向回listScore.jsp
// ScoreServlet.java 核心片段 @WebServlet("/score/add") public class ScoreServlet extends HttpServlet { private ScoreDao scoreDao = new ScoreDao(); @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding("UTF-8"); Integer studentId = Integer.valueOf(req.getParameter("studentId")); String courseName = req.getParameter("courseName"); BigDecimal scoreValue = new BigDecimal(req.getParameter("scoreValue")); Score score = new Score(); score.setStudentId(studentId); score.setCourseName(courseName); score.setScore(scoreValue); boolean ok = scoreDao.insert(score); if (ok) { resp.sendRedirect("list.jsp?studentId=" + studentId); } else { req.setAttribute("error", "成绩插入失败"); req.getRequestDispatcher("error.jsp").forward(req, resp); } } }@WebServlet("/score/add")是Servlet 3.0的注解路由,省去web.xml里写一堆Mapping配置。req.setCharacterEncoding("UTF-8")必须放在doPost最前面,因为POST请求体的编码在第一次读取参数前就要确定,放晚了读出来的中文全是问号。
这条链路走通后,学生成绩管理系统最核心的"录入一条成绩"就完整了。查询和统计在此基础上扩展:按学号查、按班级查、按课程查,SQL里加AVG(score)算平均分,加COUNT(*)算人数,再加SUM(score)做总分统计。这部分代码走读清楚,基本就掌握了整个项目的五脏六腑。
4. 让系统跑起来:MySQL初始化、JDBC连接与Tomcat配置
4.1 SQL脚本导入与初始数据验证
数据库脚本导入前,先确认MySQL版本。课程设计包最常见的适配范围是MySQL 5.7和8.0,执行导入:
mysql -u root -p < sql/init.sql输入密码后没有任何报错回到命令行,说明脚本执行成功。紧接着验证数据是否进去了:
mysql -u root -p -e "USE student_db; SHOW TABLES; SELECT * FROM student;"如果init.sql里没有CREATE DATABASE语句,需要先手动建库再导入。另外提醒一句:有的课程设计脚本为了演示方便,开头是DROP DATABASE IF EXISTS student_db,这种脚本导入前一定逐行看一遍,别把本机已有的同名库误删了。这是个黑匣子操作,不看脚本直接跑,翻车概率很高。
4.2 JDBC驱动版本与连接URL参数配置
前面ScoreDao里出现过JDBC三要素:URL、驱动类、账号密码。大多数情况下只需要改USER和PASSWORD,但有个高频坑是驱动类和MySQL版本不匹配:
| MySQL版本 | 驱动类名 |
|---|---|
| 5.7及以前 | com.mysql.jdbc.Driver |
| 8.0及以上 | com.mysql.cj.jdbc.Driver |
如果驱动类名和版本不匹配,启动时报ClassNotFoundException或Loading class com.mysql.jdbc.Driver failed。另一个麻烦是驱动jar包版本过旧,比如lib目录里放的是mysql-connector-java 5.1.x,而本机MySQL是8.0,虽然驱动类名改成com.mysql.cj.jdbc.Driver,但MySQL 8默认认证方式是caching_sha2_password,旧驱动不认,报Public Key Retrieval is not allowed。
解决办法有两种:一是换到8.x版本的驱动jar,二是URL后面追加allowPublicKeyRetrieval=true。我一般选择换jar包,因为新驱动的SSL和时区处理更完善,顺手把useSSL=false&serverTimezone=Asia/Shanghai补上,一次到位。
// DBUtil.java 连接池版本,适合稍微进阶的工程 public class DBUtil { private static final String URL = "jdbc:mysql://localhost:3306/student_db?useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=utf8"; private static final String USER = "root"; private static final String PASS = "123456"; public static Connection getConnection() throws SQLException { return DriverManager.getConnection(URL, USER, PASS); } }提示:不要把数据库密码硬编码后提交到Git仓库。课程设计包里没有部署环境,但养成从properties文件读密码的习惯,对以后进团队协作很重要。
4.3 配置Tomcat并验证登录流程
Web版启动流程:
- IDEA里配置好Tomcat后,点绿色三角启动
- 启动日志出现
Server startup in [xxx] milliseconds后,浏览器访问http://localhost:8080/项目名 - 进入登录页,找到README或init.sql里的初始账号密码
初始账号最常见的是admin / admin或admin / 123456。查初始账号有个技巧:在IDEA里全局搜索login相关字符串,或者直接打开LoginServlet看它从哪个表取账号。有时账号不存数据库,而是在代码里硬编码,搜索equals("admin")就能定位到。
如果压缩包里是桌面版,启动方式更简单:右键Main类,Run 'Main.main()',控制台会弹出窗口界面。桌面版通常不需要Tomcat,但数据库连接依然要配置到位。启动成功后,第一时间测试两个动作:录入一条成绩、按学号查询这条成绩,确认链路是通的。
5. 常见问题避坑指南:五处高概率翻车与排查
5.1 中文乱码:问号和口口从哪来,三层编码一次调对
现象:页面显示学生姓名变成"张??"或者"寮犱笁"这类乱码。
原因:三层编码不一致——文件本身是GBK编码、数据库表用utf8mb4、页面contentType写的ISO-8859-1,任何一个不对齐都会出问题。
解决:第一步,IDEA右下角File Encoding先看是GBK还是UTF-8,如果是GBK就把文件另存为UTF-8。第二步,确认JSP页面头部有pageEncoding="UTF-8"。第三步,数据库连接URL带上characterEncoding=utf8。三层全对齐,中文才稳定。乱码是全链路问题,不要只改一处就指望好。
5.2 JDBC驱动加载失败与连接超时:版本和端口逐个排查
现象:运行报ClassNotFoundException: com.mysql.cj.jdbc.Driver,或者Communications link failure。
原因:前者是jar没引入或驱动类名写错;后者是MySQL没启动、端口不对、或防火墙拦截。
解决:驱动类名按上面章节的表格对照。连接超时先确认MySQL能不能连:
mysql -u root -p -h 127.0.0.1 -P 3306能连上再看项目URL端口是否写的3306,有的机器装了宝塔面板,MySQL端口被改成3307,URL没跟着改就连不上。确认端口后还报错,用telnet 127.0.0.1 3306或nc -zv 127.0.0.1 3306验证TCP层通不通。
5.3 Tomcat端口被占用:改端口比杀进程更省心
现象:启动Tomcat时控制台报Port 8080 is already in use。
原因:上次启动的Tomcat没完全关闭,或者机器上刚好有别的进程占了8080。
解决:在Run Configuration里把HTTP port改成8081,重启Tomcat。这是最省事的做法,杀进程容易误伤别的正在跑的服务,而且治标不治本。如果改了端口还报占用,再看启动日志里有没有第二个Tomcat实例在跑。
5.4 中文路径导致资源加载失败:搬到纯英文目录
现象:项目解压在D:\下载\Java学生成绩管理系统\这样的路径下,启动后页面图片、CSS加载404,或运行时日志出现诡异的路径拼接错误。
原因:老版本Tomcat和IDEA内置Tomcat对非ASCII路径支持不完善,路径里的中文导致资源定位失败。
解决:把整个项目剪切到纯英文路径,比如D:\code\student-score-system。这个坑在Windows上很普遍,用户名为中文或解压到桌面、下载目录都会触发。改完路径后,记得让IDEA重新识别项目根目录,避免旧路径的索引缓存残留。
5.5 IDE缓存导致修改不生效:重编译和热更新配置
现象:改了Java代码,重新启动Tomcat,页面行为还是旧的。
原因:IDEA没有触发增量编译,或Tomcat deployment的exploded目录没有同步最新class文件。
解决:Build -> Rebuild Project强制全量编译,还是在Tomcat配置里把On Update action设为Redeploy,On frame deactivation设为Update resources。后者配置好后,改完代码IDEA会自动更新到Tomcat运行目录,省去手动重启。这条血泪经验是在一个bug上耗了一下午总结出来的,最后发现只是没编译新的class。
6. 进阶验证:用排序和日志确认这个成绩系统真的可靠
系统能跑只是第一步。我接手这类项目时,都会花半小时做三件事,确认它不是"纸面能跑"。
第一,验证排序逻辑。查询成绩列表时,如果原项目用SQL的ORDER BY直接排,没问题;如果是在Java侧排序,把sort函数用法java落到代码里:
// 按成绩降序,用Comparator list.sort((s1, s2) -> s2.getScore().compareTo(s1.getScore()));Comparator配合Lambda表达式,比手写冒泡排序稳妥得多。Java集合框架底层是归并排序,数据量再大也不会栈溢出,而自己写的冒泡排序在几百条成绩时性能还行,数据量翻倍后就开始卡了。
第二,在DAO层临时加一行System.out.println打印执行的SQL和受影响行数。插入一条成绩后,立刻在数据库里SELECT * FROM score ORDER BY id DESC LIMIT 1看到新记录,这比只看页面返回成功更有说服力。
第三,用一组已知数据反推统计结果。比如录入三名学生成绩80、90、95,平均分应该是88.33,及格率100%。页面显示88.3还是88.33,对照一下四舍五入规则,就能揪出浮点精度或格式化问题。
这三个验证全过,我才敢说这个学生成绩管理系统交付给老师或者作为课程设计提交,不会当场翻车。我习惯把这几条验证SQL和命令挂在调试清单里,每次拿到同类项目都照着走一遍,省得临时拍脑袋。希望帮到你。
本文还有配套的精品资源,点击获取