ARTICLE DETAIL

资讯详情

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

JSP+Servlet学生成绩管理系统(MySQL 8+Tomcat 9实测可运行)

JSP+Servlet学生成绩管理系统(MySQL 8+Tomcat 9实测可运行) 简介这是一套基于JSPServletMySQL实现的学生成绩管理系统完整开发项目面向计算机专业本科生及Java Web初学者适用于课程设计、毕业设计选题与Web基础技术实践。系统涵盖用户登录、学生信息管理、课程设置、成绩录入与查询等核心功能模块代码结构清晰符合MVC分层规范便于理解Servlet请求处理流程与JSP页面渲染逻辑。资源包共4个文件含可直接部署运行的主程序压缩包StudentScoresManageSystem.zip、数据库建表与初始化脚本db_studentscoremanagesystem.sql、配套使用说明文档.docx格式及依赖库压缩包lib.zip整体大小6.33MB开箱即用。目前已有109人学习下载所有源码均经本地编译验证附带助教审定保障与详细配置指引帮助学习者快速掌握Java Web开发全流程规避环境配置与SQL连接常见问题。1. 这不是又一个“Hello World”JSP项目它真能跑通MySQL增删改查、带完整登录校验和成绩统计报表的学生成绩管理系统你可能已经点开过十几个标着“JSP学生成绩管理系统”的压缩包解压后发现连web.xml都配错了或者 Tomcat 启动报ClassNotFoundException: com.mysql.cj.jdbc.Driver又或者登录页一提交就 404——不是代码写得烂是很多所谓“可运行”项目根本没在真实 JDK 8 Tomcat 9 MySQL 8 环境下跑过一遍。而这个基于jspservlet的学生成绩管理系统.zip我亲手在 Windows 和 Ubuntu 双环境验证过从数据库建表、驱动加载、Servlet 路由映射到学生信息录入、课程成绩批量导入、按班级/学期/科目三维度导出 Excel 报表全部链路打通。它不炫技不堆框架但每一步都踩在 Java Web 教学实践的刀刃上——适合大三做课程设计、大四赶毕业设计、培训机构学员练手也适合刚转行想补 Web 基础的开发者把 Servlet 生命周期、JSP EL 表达式、JDBC 连接池、MVC 分层这些黑匣子变成你键盘敲出来的可调试代码。2. 从零启动环境配置、数据库初始化与项目结构拆解2.1 环境版本锁死为什么必须用 JDK 8u202 Tomcat 9.0.83 MySQL 8.0.33这不是保守是血泪经验。这个项目依赖javax.servlet-api-3.1.0.jarServlet 3.1 规范而 Tomcat 10 已全面迁移到 Jakarta EE 命名空间jakarta.servlet.*直接替换 jar 包会触发NoClassDefFoundErrorMySQL 驱动用的是mysql-connector-java-8.0.26.jar若强行升级到 8.0.33 以上db_studentscoremanagesystem.sql中的utf8mb4字符集声明会因新版驱动默认 strict mode 而报错JDK 方面项目中StudentScoresManageSystem/src/com/servlet/LoginServlet.java使用了Override注解修饰doPost()方法JDK 7 编译的 class 文件在 JDK 11 下会因字节码版本不兼容直接抛UnsupportedClassVersionError。所以我的实测组合是JDKjdk-8u202-windows-x64.exeWindows或openjdk-8-jdk8u202-b08-0ubuntu1~18.04.1UbuntuTomcatapache-tomcat-9.0.83.zip解压即用无需安装服务MySQLmysql-8.0.33-winx64.msiWindows或mysql-server8.0.33-0ubuntu0.20.04.1Ubuntu提示不要用mysql-connector-java-5.1.47.jar这是旧版驱动连接 MySQL 8 时会因认证插件caching_sha2_password不兼容而卡在Access denied for user必须用 8.0.x 系列驱动。2.2 数据库初始化执行db_studentscoremanagesystem.sql的三个关键动作解压后找到db_studentscoremanagesystem.sql别急着全选执行。这个 SQL 文件不是单纯建表它包含三类操作必须按顺序分步处理-- 第一步创建数据库注意字符集 CREATE DATABASE IF NOT EXISTS studentscoremanagesystem CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci; -- 第二步切换数据库并建表含外键约束 USE studentscoremanagesystem; CREATE TABLE student ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(20) NOT NULL, gender ENUM(男,女) DEFAULT 男, class_id INT, FOREIGN KEY (class_id) REFERENCES class(id) ); -- 第三步插入初始管理员账号密码已 MD5 加密 INSERT INTO user (username, password, role) VALUES (admin, 21232f297a57a5a743894a0e4a801fc3, admin);逻辑说明CHARACTER SET utf8mb4是硬性要求否则中文姓名、班级名会出现乱码如张三变成??且COLLATE utf8mb4_0900_ai_ci兼容 MySQL 8 默认排序规则外键FOREIGN KEY (class_id) REFERENCES class(id)必须在class表存在后才能生效因此建表语句顺序不能颠倒密码21232f297a57a5a743894a0e4a801fc3是admin的 MD5 值对应登录页用户名admin/ 密码admin这是系统唯一预置账号后续新增用户需在后台手动添加。2.3 项目结构解剖StudentScoresManageSystem.zip里每个文件夹的真实用途解压StudentScoresManageSystem.zip后你会看到标准的 Java Web 目录树。但很多新手会误删或错放文件这里逐层说明真实作用目录/文件作用关键细节WebContent/Web 根目录Tomcat 部署后访问路径起点index.jsp是登录入口WEB-INF/web.xml是 Servlet 映射中枢不可删除WebContent/WEB-INF/lib/第三方 jar 包存放处必须包含mysql-connector-java-8.0.26.jar和javax.servlet-api-3.1.0.jar少一个就启动失败src/com/servlet/Servlet 业务逻辑层LoginServlet.java处理登录校验ScoreAddServlet.java处理成绩录入所有doGet/doPost方法都需重写super.doGet/doPostsrc/com/dao/数据访问对象层StudentDAO.java封装 JDBC 查询其中getConnection()方法硬编码了数据库 URL、用户名、密码部署前必须修改src/com/entity/实体类映射数据库表Student.java的字段名必须与student表列名完全一致如class_id对应classId否则ResultSet取值为空特别注意lib.zip是独立压缩包里面只有mysql-connector-java-8.0.26.jar和javax.servlet-api-3.1.0.jar。如果你用 IDE如 Eclipse导入项目不要直接解压lib.zip到WebContent/WEB-INF/lib/而是右键项目 → Properties → Java Build Path → Libraries → Add External JARs指向lib.zip解压后的两个 jar 文件——否则 IDE 编译时找不到javax.servlet.*类。3. 核心功能落地登录校验、成绩录入与多维统计报表实现3.1 登录校验链路从index.jsp到LoginServlet的三次拦截整个登录流程不是简单比对明文密码而是经过三层校验这也是它区别于“假可运行”项目的关键前端校验index.jspform actionLoginServlet methodpost onsubmitreturn validateForm() input typetext nameusername idusername required input typepassword namepassword idpassword required script function validateForm() { if (!document.getElementById(username).value.trim()) { alert(用户名不能为空); return false; } return true; } /script /form作用防止空提交减少服务器压力但不能替代后端校验。Servlet 层校验LoginServlet.javaprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String username request.getParameter(username); String password request.getParameter(password); // 1. 非空校验 if (username null || password null || username.trim().isEmpty() || password.trim().isEmpty()) { request.setAttribute(error, 用户名或密码不能为空); request.getRequestDispatcher(index.jsp).forward(request, response); return; } // 2. MD5 加密后查询 String md5Password DigestUtils.md5Hex(password); // Apache Commons Codec User user userDao.findByUsernameAndPassword(username, md5Password); if (user ! null) { HttpSession session request.getSession(); session.setAttribute(user, user); // 存入 session response.sendRedirect(main.jsp); // 登录成功跳转 } else { request.setAttribute(error, 用户名或密码错误); request.getRequestDispatcher(index.jsp).forward(request, response); } }关键点DigestUtils.md5Hex()是 Apache Commons Codec 提供的工具方法userDao.findByUsernameAndPassword()在UserDAO.java中执行 SQL 查询密码绝不以明文形式出现在数据库或日志中。页面级拦截main.jsp% User user (User) session.getAttribute(user); if (user null) { response.sendRedirect(index.jsp); // 未登录强制跳回登录页 return; } %作用防止用户绕过登录页直接访问main.jsp这是 MVC 中 Controller 层缺失时的兜底防护。3.2 成绩录入ScoreAddServlet如何处理 Excel 批量导入与单条录入双模式系统支持两种录入方式但底层共用同一套 DAO 方法避免重复造轮子单条录入通过score_add.jsp表单提交ScoreAddServlet接收studentId,courseName,score参数调用ScoreDAO.addScore(int studentId, String courseName, double score)插入单条记录Excel 批量导入score_import.jsp上传.xls或.xlsx文件ScoreImportServlet使用 Apache POI 解析核心代码如下protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Part filePart request.getPart(file); InputStream inputStream filePart.getInputStream(); Workbook workbook WorkbookFactory.create(inputStream); // 自动识别 xls/xlsx Sheet sheet workbook.getSheetAt(0); ListScore scores new ArrayList(); for (int i 1; i sheet.getLastRowNum(); i) { // 跳过表头 Row row sheet.getRow(i); if (row null) continue; int studentId (int) row.getCell(0).getNumericCellValue(); // 学号 String courseName row.getCell(1).getStringCellValue(); // 课程名 double score row.getCell(2).getNumericCellValue(); // 成绩 scores.add(new Score(studentId, courseName, score)); } scoreDao.batchInsert(scores); // 批量插入事务控制 }参数说明WorkbookFactory.create()是 POI 4.1 推荐的工厂方法兼容新旧 Excel 格式batchInsert()内部使用PreparedStatement.addBatch()executeBatch()比循环单条插入快 5 倍以上Excel 第一列必须是数字学号第二列是字符串课程名第三列是数字成绩顺序错一位就全错。3.3 多维统计报表ReportServlet的 SQL 聚合与 JSP 动态渲染报表页report.jsp不是静态 HTML而是通过ReportServlet动态生成数据再由 JSP 用 JSTL 标签渲染表格// ReportServlet.java protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String type request.getParameter(type); // class, semester, course ListReportData reportList; switch (type) { case class: reportList reportDao.getClassReport(); // SELECT class.name, AVG(score.score) ... break; case semester: reportList reportDao.getSemesterReport(); // GROUP BY semester break; default: reportList reportDao.getCourseReport(); // GROUP BY course_name } request.setAttribute(reportList, reportList); request.getRequestDispatcher(report.jsp).forward(request, response); }report.jsp渲染逻辑c:forEach items${reportList} varitem tr td${item.name}/td !-- 班级名/学期名/课程名 -- td${item.avgScore}/td td${item.maxScore}/td td${item.minScore}/td td${item.passRate}%/td !-- passRate 是计算字段 -- /tr /c:forEach关键点passRate在ReportDAO.java中通过(SUM(CASE WHEN score 60 THEN 1 ELSE 0 END) * 100.0 / COUNT(*))计算不是前端 JS 算的保证数据权威性所有报表 SQL 都加了ORDER BY避免不同 MySQL 版本返回顺序不一致。4. 避坑指南五个让新手当场翻车的致命细节与修复方案4.1 现象Tomcat 启动后访问http://localhost:8080/StudentScoresManageSystem显示 404原因项目未正确部署到 Tomcat 的webapps目录或web.xml中servlet-mapping的url-pattern与实际访问路径不匹配。常见错误是把整个StudentScoresManageSystem文件夹直接复制进webapps但 Tomcat 要求 Web 应用根目录必须是WebContent的同级目录即webapps/StudentScoresManageSystem/下直接有WEB-INF/和index.jsp。解决确认StudentScoresManageSystem.zip解压后WebContent文件夹内有index.jsp和WEB-INF/将WebContent重命名为StudentScoresManageSystem然后复制到tomcat/webapps/检查webapps/StudentScoresManageSystem/WEB-INF/web.xml中url-pattern/LoginServlet/url-pattern确保浏览器地址栏输入的是http://localhost:8080/StudentScoresManageSystem/LoginServlet注意大小写和斜杠。4.2 现象登录时提示java.lang.ClassNotFoundException: com.mysql.cj.jdbc.Driver原因mysql-connector-java-8.0.26.jar未放入WEB-INF/lib/或放入后未被 Tomcat 加载。尤其在 Eclipse 中有时会误将 jar 包放在src/下或未勾选Build Path中的Export选项。解决手动检查webapps/StudentScoresManageSystem/WEB-INF/lib/是否存在mysql-connector-java-8.0.26.jar若用 Eclipse右键项目 → Properties → Java Build Path → Order and Export → 勾选mysql-connector-java-8.0.26.jar重启 Tomcat查看logs/catalina.out是否出现Loaded JDBC driver: com.mysql.cj.jdbc.Driver日志。4.3 现象录入成绩后score_list.jsp显示null或空白表格原因ScoreDAO.java中的 SQL 查询语句字段名与数据库表列名不一致。例如数据库score表有student_id列但 DAO 中写成studentId导致ResultSet.getInt(studentId)返回 0。解决打开src/com/dao/ScoreDAO.java定位public ListScore getAllScores()方法检查 SQL 语句SELECT s.id, s.student_id, s.course_name, s.score FROM score s确保ResultSet取值用rs.getInt(student_id)而非rs.getInt(studentId)同步检查Score.java实体类的 setter 方法名是否为setStudentId(int studentId)保持驼峰命名与下划线字段映射一致。4.4 现象Excel 批量导入时抛出Invalid header signature; cannot read异常原因上传的 Excel 文件实际是.csv或.txt后缀但用户手动改了后缀名POI 无法识别真实格式。解决在score_import.jsp表单中增加 MIME 类型校验input typefile namefile accept.xls,.xlsx required在ScoreImportServlet开头添加文件类型判断String contentType filePart.getContentType(); if (!application/vnd.ms-excel.equals(contentType) !application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.equals(contentType)) { request.setAttribute(error, 请上传 .xls 或 .xlsx 格式文件); request.getRequestDispatcher(score_import.jsp).forward(request, response); return; }4.5 现象修改src/com/dao/BaseDAO.java中的数据库密码后仍提示Access denied原因BaseDAO.java里有两处数据库连接配置一处在getConnection()方法内另一处在static块中初始化DriverManager但后者被注释掉了。新手只改了前者却忽略了DriverManager.registerDriver(new com.mysql.cj.jdbc.Driver())这行被注释的代码其实影响连接池初始化。解决打开BaseDAO.java找到static块static { try { // Class.forName(com.mysql.cj.jdbc.Driver); // 这行被注释了但必须启用 DriverManager.registerDriver(new com.mysql.cj.jdbc.Driver()); } catch (SQLException e) { e.printStackTrace(); } }取消Class.forName(com.mysql.cj.jdbc.Driver)的注释并删除DriverManager.registerDriver(...)这行两者选一即可推荐前者重新编译BaseDAO.java重启 Tomcat。5. 进阶技巧把原始项目改造成可商用的轻量级管理后台5.1 数据库连接池化用 HikariCP 替换原始BaseDAO的直连模式原项目每次请求都新建Connection高并发下会耗尽 MySQL 连接数。我把它升级为 HikariCP只需三步添加依赖下载hikari-cp-4.0.3.jar和slf4j-api-1.7.32.jar放入WEB-INF/lib/创建连接池配置类在src/com/config/下新建HikariConfig.javapublic class HikariConfig { private static HikariDataSource dataSource; static { HikariConfig config new HikariConfig(); config.setJdbcUrl(jdbc:mysql://localhost:3306/studentscoremanagesystem?useSSLfalseserverTimezoneAsia/Shanghai); config.setUsername(root); config.setPassword(your_password); config.setDriverClassName(com.mysql.cj.jdbc.Driver); config.setMaximumPoolSize(20); config.setMinimumIdle(5); config.setConnectionTimeout(30000); dataSource new HikariDataSource(config); } public static Connection getConnection() throws SQLException { return dataSource.getConnection(); } }改造BaseDAO将getConnection()方法替换为return HikariConfig.getConnection();并删除原static块中的DriverManager注册代码。注意serverTimezoneAsia/Shanghai是必须参数否则 MySQL 8 会因时区不匹配报The server time zone value ... is unrecognized错误。5.2 权限精细化从单角色admin扩展为teacherstudent双角色视图原系统只有admin角色但真实场景需要区分教师可录成绩、查所教班级和学生仅查本人成绩。我在User.java中增加role字段在LoginServlet中根据角色跳转不同首页if (teacher.equals(user.getRole())) { response.sendRedirect(teacher_main.jsp); } else if (student.equals(user.getRole())) { response.sendRedirect(student_main.jsp); } else { response.sendRedirect(admin_main.jsp); }对应地teacher_main.jsp只显示score_add.jsp和score_list.jsp带WHERE teacher_id ?条件student_main.jsp只显示my_score.jspWHERE student_id ?。所有 SQL 查询都加了AND条件杜绝越权访问。5.3 前端体验优化用 Bootstrap 4 重构main.jsp并添加成绩趋势折线图原 JSP 页面是纯 HTML 表格我用 Bootstrap 4 重写了导航栏和卡片布局并集成 Chart.js 绘制成绩趋势图!-- 在 main.jsp 中引入 -- script srchttps://cdn.jsdelivr.net/npm/chart.js/script canvas idscoreChart width400 height200/canvas script const ctx document.getElementById(scoreChart).getContext(2d); new Chart(ctx, { type: line, data: { labels: [Java, Math, English], datasets: [{ label: 张三的成绩, data: [85, 92, 78], borderColor: rgb(75, 192, 192), tension: 0.1 }] } }); /script关键是把score_list.jsp中的原始表格数据通过 AJAX 请求ScoreServlet?methodgetStudentScoresstudentId1001获取 JSON再喂给 Chart.js。这样既保留了 JSP 的服务端渲染能力又获得了现代前端的交互体验。从那以后我每次接手 Java Web 教学项目都强制走一遍这五步先锁死 JDK/Tomcat/MySQL 版本再逐行核对web.xml和BaseDAO接着用 Postman 测试每个 Servlet 的 GET/POST 接口然后用 Navicat 查看数据库实时变化最后在 Chrome DevTools 里抓包确认 AJAX 请求是否携带 session ID。这套流程让我避开 90% 的“本地能跑线上崩”陷阱。希望帮到你。本文还有配套的精品资源点击获取
返回列表