
简介这是一套面向高校计算机相关专业学生与Java Web初学者、课程设计开发者的JavaEE学生成绩管理系统完整源码包基于JSP、Servlet、JDBC与MySQL实现并引入MD5加密算法覆盖学生、教师、管理员三类角色。学生端支持考勤管理、请假、选课、成绩查询与个人信息修改教师端在此基础上增加请假审核、选课信息管理、学生与班级信息管理、课程管理、成绩管理及成绩导入导出、可视化统计管理员端额外提供教师管理功能。资源共93个文件以java源码、class字节码、jsp页面为主辅以jar依赖、css样式、properties与xml配置、sql建库脚本及doc说明文档压缩包约1.7MB代码完整且注释详细。已有1487人学习下载适合作为课程设计、毕业设计或JavaEE入门练手项目帮助读者快速理解分层开发思路、数据库设计与权限控制实现。1. 从一份 .rar 说起JavaEE 成绩管理系统到底交付了什么拿到「javaEE学生成绩管理系统源码数据库文档.rar」这个包很多人第一反应是解压、找 main、点运行。但真正决定这套东西能不能用、能不能改成自己学院要的样子往往不是代码写得多漂亮而是三件事有没有对齐数据库表结构是否覆盖了成绩录入、修改、统计、导出这条完整链路后端分层是否把学生、教师、管理员三种角色的权限切干净文档是否写清了部署环境和初始化数据。这个标题对应的不是玩具 demo而是一套典型的课程设计级 JavaEE 项目常见技术栈是 Servlet/JSP 或 SSMSpring SpringMVC MyBatis数据库多为 MySQL前端用 JSP jQuery 或 Bootstrap。它适合三类人正在做课程设计的学生、需要快速搭一套内部成绩管理原型的开发者、以及想拿一个完整 CRUD 项目练手数据库增删改查和分层思想的人。下面按「先看懂结构、再跑起来、再改得动、最后避坑」的顺序拆开讲。2. 拆包先看三样东西源码分层、数据库脚本、文档目录2.1 源码目录怎么读才不迷路解压后不要急着导入 IDE。先看根目录有没有src、WebContent或webapp、lib、sql、doc这几类文件夹。典型 JavaEE 项目的源码结构是项目根/ ├── src/ │ ├── com.xxx.controller/ # 控制层接收请求 │ ├── com.xxx.service/ # 业务层成绩计算、权限判断 │ ├── com.xxx.dao/ # 数据访问层SQL 或 MyBatis Mapper │ ├── com.xxx.entity/ # 实体类对应数据库表 │ └── com.xxx.util/ # 数据库连接、工具类 ├── WebContent/ │ ├── WEB-INF/web.xml # 部署描述符 │ ├── jsp/ # 页面 │ └── static/ # css、js、图片 ├── sql/ # 建库建表脚本 └── doc/ # 文档判断技术栈的方法很直接看web.xml里有没有 Spring 的ContextLoaderListener看src下有没有applicationContext.xml或mybatis-config.xml。如果有就是 SSM如果只有 Servlet 映射就是原生 Servlet/JSP。这一步决定了你后面改代码的方式——SSM 改 Mapper XML原生 Servlet 改 DAO 里的 JDBC 代码。提示如果lib目录里有一堆 jar 但没有 Maven 的pom.xml说明这是传统 Web 项目导入 Eclipse 时要手动 Build Path导入 IDEA 时要选「Add as Library」。2.2 数据库脚本先跑一遍再谈改代码sql目录里通常有一个.sql文件里面包含CREATE DATABASE、CREATE TABLE、INSERT初始化数据。先别改代码先把库建起来。常见表包括student学号、姓名、班级、teacher工号、姓名、course课程号、课程名、学分、score学号、课程号、分数、学期、user登录账号、密码、角色。执行顺序是# 登录 MySQL 后执行 source /path/to/项目名.sql; # 或者命令行直接导入 mysql -u root -p 数据库名 项目名.sql执行完用SHOW TABLES;确认表数量再用SELECT * FROM user;看默认账号。很多包里的默认密码是明文123456或 MD5 后的值这决定了你登录时填什么。如果导入报错「Unknown character set」把脚本里的utf8mb4改成utf8再试如果报外键约束错误先执行SET FOREIGN_KEY_CHECKS0;再导入导入后记得改回 1。2.3 文档目录决定你能不能一次跑通doc目录里一般有「部署说明」「需求分析」「数据库设计」三类文档。部署说明里最关键的是三行JDK 版本、Tomcat 版本、MySQL 版本。JavaEE 老项目常见组合是 JDK 1.8 Tomcat 8.5 MySQL 5.7。如果文档写的是 JDK 1.7 而你现在用 JDK 17编译时大概率遇到Unsupported class file major version。这时候要么装一个 JDK 8要么在 IDE 里把项目 SDK 降到 8。数据库设计文档里的 ER 图或表字段说明是你后面改成绩计算逻辑时唯一能对照的依据别跳过。3. 把项目跑起来环境配置、连接池、登录验证三步走3.1 环境配置的最小检查清单在导入 IDE 之前先确认本机环境。下面这张表是我一般会逐项打勾的检查项常见要求不满足时的现象JDK1.8编译报版本不匹配Tomcat8.5 或 9.0启动报 Servlet 版本错误MySQL5.7 或 8.0连接报时区或驱动错误IDEEclipse/IDEA导入后红叉满屏数据库驱动mysql-connector-java启动报 ClassNotFoundMySQL 8.0 要特别注意驱动类名从com.mysql.jdbc.Driver变成了com.mysql.cj.jdbc.Driver连接 URL 还要加serverTimezoneAsia/Shanghai。如果项目里写的是老驱动你换了新 MySQL 就会连不上。解决办法是改db.properties或jdbc.propertiesjdbc.drivercom.mysql.cj.jdbc.Driver jdbc.urljdbc:mysql://localhost:3306/score_db?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai jdbc.usernameroot jdbc.password你的密码改完不要忘了把mysql-connector-java的 jar 换成 8.x 版本否则驱动类名对了但协议不兼容。3.2 数据库连接池为什么老项目容易翻车很多课程设计项目直接用DriverManager.getConnection()每次请求新建连接。学生自己测没问题一旦多人同时登录数据库连接数暴涨Tomcat 报Too many connections。常见做法是换成 Druid 或 C3P0 连接池。以 Druid 为例在src下新建druid.propertiesdriverClassNamecom.mysql.cj.jdbc.Driver urljdbc:mysql://localhost:3306/score_db?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai usernameroot password你的密码 initialSize5 maxActive20 maxWait3000然后在工具类里加载public class DBUtil { private static DataSource dataSource; static { try { Properties props new Properties(); props.load(DBUtil.class.getClassLoader() .getResourceAsStream(druid.properties)); dataSource DruidDataSourceFactory.createDataSource(props); } catch (Exception e) { e.printStackTrace(); } } public static Connection getConnection() throws SQLException { return dataSource.getConnection(); } }initialSize是启动时建立的连接数maxActive是最大连接数maxWait是获取连接的超时毫秒数。这三个参数决定并发能力。课程设计场景initialSize5、maxActive20足够如果要做成学院级系统maxActive可以提到 50但要同步调大 MySQL 的max_connections。3.3 登录验证与角色跳转的常见实现登录流程一般是login.jsp提交账号密码 →LoginServlet或UserController接收 → 查user表 → 根据role字段跳转到学生、教师或管理员首页。核心代码通常长这样RequestMapping(/login) public String login(String username, String password, HttpSession session) { User user userService.findByUsername(username); if (user null || !user.getPassword().equals(MD5Util.md5(password))) { return login; } session.setAttribute(currentUser, user); if (admin.equals(user.getRole())) { return redirect:/admin/index; } else if (teacher.equals(user.getRole())) { return redirect:/teacher/index; } else { return redirect:/student/index; } }这里有两个容易忽略的点一是密码比对方式要和数据库里存的一致如果库里是 MD5代码里也要 MD5二是session里存的用户对象要包含角色字段否则拦截器无法判断权限。如果登录后一直跳回登录页先看session是否被正确设置再看拦截器有没有把静态资源也拦了。4. 改得动才算真跑通成绩录入、统计查询、导出三个改造点4.1 成绩录入的批量提交与事务原始项目里成绩录入往往是单条INSERT一个班 40 人就要点 40 次。改成批量提交是第一个有价值的改造。在 Service 层加事务Transactional public void batchInsertScores(ListScore scoreList) { for (Score score : scoreList) { scoreMapper.insert(score); } }对应的 Mapper XML 用foreach批量插入insert idbatchInsert parameterTypejava.util.List INSERT INTO score(student_id, course_id, score, term) VALUES foreach collectionlist itemitem separator, (#{item.studentId}, #{item.courseId}, #{item.score}, #{item.term}) /foreach /insertTransactional保证要么全成功要么全回滚避免录了一半失败后数据不一致。参数上要注意score字段类型如果是decimal(5,2)前端传「85」和「85.5」都能存但传「85.555」会被截断。批量插入时如果列表为空foreach会生成非法 SQL所以 Service 里要先判空。4.2 统计查询平均分、及格率、排名怎么写成绩统计是这类系统的核心价值。常见需求是某课程平均分、及格率、班级排名。SQL 写法-- 平均分与及格率 SELECT course_id, AVG(score) AS avg_score, SUM(CASE WHEN score 60 THEN 1 ELSE 0 END) / COUNT(*) AS pass_rate FROM score WHERE term 2024-2025-1 GROUP BY course_id; -- 班级排名 SELECT s.student_id, s.name, sc.score, RANK() OVER (ORDER BY sc.score DESC) AS rank_no FROM score sc JOIN student s ON sc.student_id s.student_id WHERE sc.course_id CS101;RANK()是 MySQL 8.0 才支持的窗口函数如果项目跑在 5.7 上要用变量模拟SELECT student_id, score, rank : rank 1 AS rank_no FROM score, (SELECT rank : 0) r WHERE course_id CS101 ORDER BY score DESC;两种写法结果一样但 5.7 的变量写法在并发查询时可能串号所以生产环境建议升级到 8.0 或用应用层排序。4.3 成绩导出 Excel 的最小实现导出功能是文档里经常提但源码里可能没写完的部分。用 Apache POI 实现public void exportExcel(HttpServletResponse response, ListScoreVO list) throws IOException { XSSFWorkbook workbook new XSSFWorkbook(); XSSFSheet sheet workbook.createSheet(成绩表); XSSFRow header sheet.createRow(0); header.createCell(0).setCellValue(学号); header.createCell(1).setCellValue(姓名); header.createCell(2).setCellValue(课程); header.createCell(3).setCellValue(分数); for (int i 0; i list.size(); i) { XSSFRow row sheet.createRow(i 1); row.createCell(0).setCellValue(list.get(i).getStudentId()); row.createCell(1).setCellValue(list.get(i).getName()); row.createCell(2).setCellValue(list.get(i).getCourseName()); row.createCell(3).setCellValue(list.get(i).getScore()); } response.setContentType(application/vnd.openxmlformats-officedocument.spreadsheetml.sheet); response.setHeader(Content-Disposition, attachment;filenamescores.xlsx); workbook.write(response.getOutputStream()); workbook.close(); }XSSFWorkbook对应.xlsxHSSFWorkbook对应.xls。数据量大时用SXSSFWorkbook避免内存溢出。导出文件名如果含中文要做 URL 编码否则浏览器下载后文件名乱码。5. 避坑与排查五个让项目跑不起来的真实原因5.1 导入后全是红叉jar 包找不到现象IDE 里import org.springframework...全部报错。原因项目不是 Maven 结构jar 在lib目录但没加入 Build Path。解决IDEA 里右键lib目录 → Add as LibraryEclipse 里右键项目 → Build Path → Configure Build Path → Add JARs。如果lib里缺 jar从文档里找依赖清单或者按报错类名去补对应 jar。5.2 启动报 404页面能开但请求全挂现象Tomcat 启动成功访问login.jsp正常但提交表单后 404。原因web.xml里的url-pattern和表单action不一致或者 SpringMVC 的DispatcherServlet映射路径写成了/但没配静态资源处理。解决先看浏览器地址栏实际请求路径再对照web.xml和 Controller 的RequestMapping。如果是 SSM检查springmvc.xml里有没有mvc:default-servlet-handler/。5.3 中文乱码成绩表里全是问号现象录入中文姓名后数据库里显示???。原因数据库字符集、连接 URL、JSP 页面编码三者不一致。解决数据库和表用utf8mb4连接 URL 加characterEncodingutf8JSP 页面顶部加% page contentTypetext/html;charsetUTF-8 %Tomcat 的server.xml里 Connector 加URIEncodingUTF-8。四处都对齐才不会乱码。5.4 修改成绩后列表不刷新现象提交修改成功返回列表页还是旧数据。原因查询用了缓存或者事务没提交。解决如果是 MyBatis 一级缓存在 Mapper 里加flushCachetrue如果是 Service 没加Transactional检查 Spring 配置里事务管理器是否生效。还有一种情况是浏览器缓存了 GET 请求改成 POST 或加时间戳参数。5.5 导出 Excel 报 POI 版本冲突现象NoSuchMethodError或ClassNotFoundException: org.apache.poi.ss.usermodel.Workbook。原因项目里同时存在多个版本的 POI jar。解决在lib里只保留一套 POIpoi、poi-ooxml、poi-ooxml-schemas版本号一致删掉重复的旧版本。如果用的是 Maven用mvn dependency:tree看冲突来源加exclusions排除。6. 进阶技巧把课程设计改成能写进简历的项目如果你不满足于「能跑就行」想让这套系统在面试里拿得出手有三个方向可以加。第一把原生 JDBC 换成 MyBatis-Plus分页查询和条件构造器能省掉大量重复 SQL代码量减少三分之一。第二加一层 Redis 缓存课程列表和统计结果用Cacheable注解面试时能聊缓存穿透和雪崩。第三把导出功能从 POI 换成 EasyExcel百万行数据不 OOM这是很多公司实际在用的方案。// EasyExcel 导出示例 EasyExcel.write(response.getOutputStream(), ScoreVO.class) .sheet(成绩表) .doWrite(scoreList);参数上注意ScoreVO的字段要用ExcelProperty(学号)注解否则表头是英文。doWrite内部是流式写入比 POI 省内存但样式定制不如 POI 灵活。验证改造是否成功不要只看页面能打开。我一般会做三件事用 JMeter 发 50 个并发请求看连接池是否耗尽把数据库停掉看系统是否优雅报错而不是白屏导出 1 万条数据看内存和耗时。这三步能暴露大部分隐藏问题。最后说个血泪经验改这类项目一定要先备份原始.rar再在 Git 里开分支。我见过太多人改到一半想回退结果原始包被覆盖只能重下。数据库脚本也要单独存一份别和代码混在一个目录里。希望帮到你。本文还有配套的精品资源点击获取