ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Java Web成绩管理系统:JSP+Servlet+MySQL实战部署指南

Java Web成绩管理系统:JSP+Servlet+MySQL实战部署指南 简介本资源是一个基于Java Web技术栈开发的学生成绩管理系统完整项目面向高校计算机专业初学者、Java Web入门学习者及课程设计实践者解决教育场景中成绩录入、查询、统计与权限管理等核心业务需求。压缩包共36个文件含10个Java后端逻辑类、9个JSP动态页面、10张运行界面截图涵盖首页、录入页、查询页、统计页等关键功能视图、3张PNG图标资源、1个web.xml配置文件及README.md说明文档整体大小2.94MB结构清晰体现MVC分层设计。目前已有33人学习下载。读者可直接部署运行完整掌握ServletJSPJDBC整合开发流程理解数据库表设计含学生、课程、成绩三张主表、用户角色权限控制实现方式并通过截图直观对照前后端交互效果与业务逻辑闭环。1. 一个能跑在 Tomcat 里的 Java Web 成绩管理后台不是 Demo是能填数据、查成绩、导 Excel 的真实闭环“基于Java的Web学生成绩管理系统.zip”——这个标题背后不是教科书里的 Servlet Hello World而是一套面向高校教务场景、具备完整 CRUD 流程、带登录鉴权、支持 MySQL 持久化、前端能渲染表格与表单的真实 Web 工程。它解决的是教师手动 Excel 录入易出错、学生查分要等通知、管理员改成绩得反复拷贝文件这类具体痛点。系统核心不在于炫技而在于用户登录后能新增班级、录入某门课所有学生成绩、按学号/姓名/课程名模糊检索、导出当前查询结果为 Excel 文件、修改单条记录并实时生效。技术栈上它典型采用 JSP Servlet JDBC 组合非 Spring Boot部署在 Tomcat 8.5数据库用 MySQL 5.7适合 Java 初学者理解 MVC 分层逻辑也适合作为 Web 期末作业或教务系统原型快速迭代。如果你正卡在“写完 Servlet 不知道怎么连数据库”“JSP 表单提交后数据没进表”“Tomcat 启动报 404 但目录结构看起来没问题”这些环节这篇就是为你写的实操指南。2. 用 JSP Servlet JDBC 搭建成绩管理系统的最小可行架构2.1 为什么选 JSP/Servlet 而不是 Spring Boot——从教学到落地的取舍逻辑当前主流 Web 开发虽已转向 Spring Boot但“基于Java的Web学生成绩管理系统.zip”这类项目仍大量采用传统 JSP/Servlet 架构原因有三第一教学穿透性更强——学生能清晰看到 HTTP 请求如何被 Servlet 接收、参数如何解析、SQL 如何拼接、结果如何转发给 JSP 渲染每一层代码都可调试、可打断点第二部署极简——无需 Maven 多模块、无需配置 application.yml、无需启动内嵌 Tomcat直接把webapps/ROOT目录丢进 Tomcat 就能跑第三兼容性兜底——老旧机房服务器常只装 JDK 8 和 Tomcat 7Spring Boot 2.7 已不支持 JDK 8而 JSP/Servlet 项目在 JDK 8 Tomcat 8.5 环境下零适配成本。注意这不是推荐“过时技术”而是强调——当你需要向非技术人员演示“成绩录入流程”、或在无外网环境的实训机房快速部署时JSP/Servlet 是更鲁棒的选择。2.2 项目目录结构必须满足 Tomcat 加载规则Tomcat 通过web.xml或注解识别 Servlet通过/WEB-INF/web.xml定义欢迎页和 URL 映射。一个可运行的最小结构如下路径以webapps/ROOT为根ROOT/ ├── index.jsp # 欢迎页重定向到 login.jsp ├── login.jsp # 登录表单POST 到 LoginServlet ├── main.jsp # 登录成功后主页面含导航栏与成绩列表 iframe ├── score/ │ ├── list.jsp # 成绩列表页含搜索表单与表格 │ ├── add.jsp # 新增成绩表单页 │ └── edit.jsp # 修改成绩表单页预填充原数据 ├── WEB-INF/ │ ├── web.xml # 配置 Servlet 映射与 welcome-file-list │ ├── classes/ │ │ └── com/example/ │ │ ├── servlet/ │ │ │ ├── LoginServlet.class │ │ │ ├── ScoreListServlet.class │ │ │ ├── ScoreAddServlet.class │ │ │ └── ScoreEditServlet.class │ │ └── dao/ │ │ ├── ScoreDAO.class │ │ └── BaseDAO.class │ └── lib/ │ └── mysql-connector-java-5.1.47.jar # JDBC 驱动必须放这里 └── js/ └── common.js # 封装 AJAX 提交、表单校验等通用逻辑提示WEB-INF目录下的资源如web.xml、classes、lib不能被浏览器直接访问这是 Tomcat 的安全机制。所有.jsp文件必须放在WEB-INF外层否则 404。2.3web.xml中三个关键配置项及其作用WEB-INF/web.xml是传统 Java Web 项目的中枢配置文件。以下三段配置缺一不可?xml version1.0 encodingUTF-8? web-app xmlnshttp://xmlns.jcp.org/xml/ns/javaee xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd version4.0 !-- 1. 设置默认欢迎页 -- welcome-file-list welcome-fileindex.jsp/welcome-file /welcome-file-list !-- 2. 配置 LoginServlet映射到 /login -- servlet servlet-nameLoginServlet/servlet-name servlet-classcom.example.servlet.LoginServlet/servlet-class /servlet servlet-mapping servlet-nameLoginServlet/servlet-name url-pattern/login/url-pattern /servlet-mapping !-- 3. 配置 ScoreListServlet处理成绩列表请求 -- servlet servlet-nameScoreListServlet/servlet-name servlet-classcom.example.servlet.ScoreListServlet/servlet-class /servlet servlet-mapping servlet-nameScoreListServlet/servlet-name url-pattern/score/list/url-pattern /servlet-mapping /web-appwelcome-file-list告诉 Tomcat当用户访问http://localhost:8080/时自动加载index.jsp而非返回 404servlet块声明 Servlet 类的全限定名包名类名Tomcat 会用反射实例化它servlet-mapping将 URL 路径如/login绑定到指定 Servlet这是请求路由的核心。注意url-pattern中的/是相对于上下文路径Context Path的ROOT应用的上下文路径为空所以/login即http://localhost:8080/login。2.4 JDBC 连接 MySQL 的五步实操与防坑要点ScoreDAO类负责所有数据库操作。以下是连接 MySQL 的标准写法以BaseDAO.java为例// src/com/example/dao/BaseDAO.java package com.example.dao; import java.sql.*; public class BaseDAO { private static final String URL jdbc:mysql://localhost:3306/school_db?useUnicodetruecharacterEncodingUTF-8serverTimezoneGMT%2B8; private static final String USER root; private static final String PASSWORD 123456; // 获取 Connection 的静态方法 public static Connection getConnection() throws SQLException { try { Class.forName(com.mysql.jdbc.Driver); // MySQL 5.x 驱动类名 } catch (ClassNotFoundException e) { throw new RuntimeException(MySQL JDBC Driver not found, e); } return DriverManager.getConnection(URL, USER, PASSWORD); } // 关闭资源的通用方法防止内存泄漏 public static void close(Connection conn, PreparedStatement pstmt, ResultSet rs) { if (rs ! null) try { rs.close(); } catch (SQLException e) {} if (pstmt ! null) try { pstmt.close(); } catch (SQLException e) {} if (conn ! null) try { conn.close(); } catch (SQLException e) {} } }URL 参数必须包含serverTimezoneGMT%2B8否则 MySQL 8.0 会报The server time zone value UTC is unrecognized错误驱动类名区分版本MySQL 5.x 用com.mysql.jdbc.DriverMySQL 8.x 用com.mysql.cj.jdbc.Driver本项目 ZIP 包中lib/mysql-connector-java-5.1.47.jar对应 5.x故用前者Connection 必须在 finally 块中关闭Servlet 是多线程环境未关闭的连接会快速耗尽数据库连接池即使本项目用的是直连也需养成习惯密码明文写死仅限本地开发生产环境必须抽离到context.xml或配置文件并加密存储。3. 实现成绩录入、查询、导出三大核心功能的代码级拆解3.1 成绩录入从表单提交到数据库插入的完整链路add.jsp提供学号、姓名、课程名、成绩四个字段的输入框提交到ScoreAddServlet!-- score/add.jsp -- form actionscore/add methodpost input typetext namestudentId placeholder学号 required / input typetext namestudentName placeholder姓名 required / input typetext namecourseName placeholder课程名 required / input typenumber namescore min0 max100 placeholder成绩 required / button typesubmit提交/button /formScoreAddServlet.java接收参数并调用 DAO// src/com/example/servlet/ScoreAddServlet.java package com.example.servlet; import com.example.dao.ScoreDAO; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class ScoreAddServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 1. 获取表单参数自动解码 UTF-8 String studentId request.getParameter(studentId); String studentName request.getParameter(studentName); String courseName request.getParameter(courseName); String scoreStr request.getParameter(score); // 2. 参数校验基础检查 if (studentId null || studentId.trim().isEmpty() || courseName null || courseName.trim().isEmpty() || scoreStr null) { request.setAttribute(error, 学号、课程名、成绩不能为空); request.getRequestDispatcher(/score/add.jsp).forward(request, response); return; } try { double score Double.parseDouble(scoreStr); if (score 0 || score 100) { request.setAttribute(error, 成绩必须在 0-100 之间); request.getRequestDispatcher(/score/add.jsp).forward(request, response); return; } // 3. 调用 DAO 插入数据库 boolean success new ScoreDAO().addScore(studentId, studentName, courseName, score); if (success) { request.setAttribute(msg, 录入成功); request.getRequestDispatcher(/score/list.jsp).forward(request, response); } else { request.setAttribute(error, 录入失败请重试); request.getRequestDispatcher(/score/add.jsp).forward(request, response); } } catch (NumberFormatException e) { request.setAttribute(error, 成绩必须为数字); request.getRequestDispatcher(/score/add.jsp).forward(request, response); } } }request.getParameter()自动处理 URL 编码JSP 表单默认application/x-www-form-urlencoded中文会编码为%E5%BC%A0%E4%B8%89Tomcat 8.5 默认用 UTF-8 解码无需额外new String(param.getBytes(ISO-8859-1), UTF-8)Double.parseDouble()替代Integer.parseInt()成绩允许小数如 89.5避免NumberFormatException插入成功后跳转到list.jsp符合 RESTful 重定向原则Post-Redirect-Get防止用户刷新导致重复提交。3.2 成绩查询支持模糊搜索与分页的 SQL 构建技巧ScoreListServlet根据keyword参数动态构建 WHERE 条件// src/com/example/servlet/ScoreListServlet.java public class ScoreListServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String keyword request.getParameter(keyword); ListScore scoreList; if (keyword null || keyword.trim().isEmpty()) { // 无搜索条件查全部 scoreList new ScoreDAO().findAll(); } else { // 有搜索条件学号、姓名、课程名任一匹配 scoreList new ScoreDAO().searchByKeyword(keyword.trim()); } request.setAttribute(scoreList, scoreList); request.getRequestDispatcher(/score/list.jsp).forward(request, response); } }ScoreDAO.searchByKeyword()方法使用PreparedStatement防止 SQL 注入// src/com/example/dao/ScoreDAO.java public ListScore searchByKeyword(String keyword) { ListScore list new ArrayList(); String sql SELECT id, student_id, student_name, course_name, score, create_time FROM t_score WHERE student_id LIKE ? OR student_name LIKE ? OR course_name LIKE ?; try (Connection conn BaseDAO.getConnection(); PreparedStatement pstmt conn.prepareStatement(sql)) { // 三个 ? 都用 %keyword% 匹配 pstmt.setString(1, % keyword %); pstmt.setString(2, % keyword %); pstmt.setString(3, % keyword %); try (ResultSet rs pstmt.executeQuery()) { while (rs.next()) { Score score new Score(); score.setId(rs.getLong(id)); score.setStudentId(rs.getString(student_id)); score.setStudentName(rs.getString(student_name)); score.setCourseName(rs.getString(course_name)); score.setScore(rs.getDouble(score)); score.setCreateTime(rs.getTimestamp(create_time)); list.add(score); } } } catch (SQLException e) { e.printStackTrace(); } return list; }LIKE ?pstmt.setString()是防注入的黄金组合绝不能用字符串拼接WHERE name LIKE % keyword %三个字段共用一个keyword简化前端逻辑用户输入“张”即可匹配学号含“张”、姓名含“张”、课程名含“张”的所有记录try-with-resources自动关闭资源Java 7 特性比手写finally更简洁安全。3.3 Excel 导出用 Apache POI 生成 .xls 文件的零依赖方案导出功能通常放在list.jsp的按钮上点击触发ScoreExportServlet!-- score/list.jsp -- a hrefscore/export?keyword% request.getParameter(keyword) ! null ? request.getParameter(keyword) : % button导出当前查询结果/button /aScoreExportServlet生成 Excel 并写入响应流// src/com/example/servlet/ScoreExportServlet.java public class ScoreExportServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String keyword request.getParameter(keyword); ListScore scoreList keyword null || keyword.trim().isEmpty() ? new ScoreDAO().findAll() : new ScoreDAO().searchByKeyword(keyword.trim()); // 创建 Excel 工作簿 HSSFWorkbook workbook new HSSFWorkbook(); HSSFSheet sheet workbook.createSheet(学生成绩表); // 表头行 HSSFRow headerRow sheet.createRow(0); String[] headers {序号, 学号, 姓名, 课程名, 成绩, 录入时间}; for (int i 0; i headers.length; i) { HSSFCell cell headerRow.createCell(i); cell.setCellValue(headers[i]); } // 数据行 for (int i 0; i scoreList.size(); i) { Score s scoreList.get(i); HSSFRow row sheet.createRow(i 1); row.createCell(0).setCellValue(i 1); row.createCell(1).setCellValue(s.getStudentId()); row.createCell(2).setCellValue(s.getStudentName()); row.createCell(3).setCellValue(s.getCourseName()); row.createCell(4).setCellValue(s.getScore()); row.createCell(5).setCellValue(new SimpleDateFormat(yyyy-MM-dd HH:mm:ss) .format(s.getCreateTime())); } // 设置响应头触发浏览器下载 response.setContentType(application/vnd.ms-excel); String fileName URLEncoder.encode(学生成绩表.xls, UTF-8); response.setHeader(Content-Disposition, attachment;filename fileName); // 写入输出流 try (OutputStream out response.getOutputStream()) { workbook.write(out); } } }HSSFWorkbook对应 .xls 格式兼容 Excel 2003 及以上无需 Office 环境纯 Java 实现URLEncoder.encode()处理中文文件名避免 Chrome 下载文件名乱码Firefox 和 Edge 也兼容response.setContentType()必须设为application/vnd.ms-excel否则浏览器可能尝试在线打开而非下载。4. Tomcat 部署与常见 404/500 错误的精准定位方法4.1 Tomcat 启动后访问http://localhost:8080/报 404 的三层排查法404 错误本质是 Tomcat 找不到请求的资源。按优先级逐层检查检查层级具体操作典型现象与修复第一层应用是否成功部署查看logs/catalina.out最后 20 行搜索deploy关键字若出现Deployment of web application archive [/path/to/tomcat/webapps/ROOT.war] has finished in [X] ms说明部署成功若无此日志检查webapps/ROOT目录是否存在是否被误删为ROOT.zip第二层URL 路径是否匹配web.xml访问http://localhost:8080/login查看catalina.out是否打印LoginServlet init日志若无日志说明url-pattern/login/url-pattern未生效检查web.xml是否放在WEB-INF/下且格式正确XML 标签闭合、命名空间无误第三层JSP 文件路径是否正确在浏览器开发者工具 Network 标签中看请求的.jsp文件状态码若list.jsp返回 404确认文件确实在ROOT/score/list.jsp而非ROOT/WEB-INF/score/list.jsp后者不可访问注意Tomcat 8.5 默认启用antiResourceLocking修改 JSP 后需重启 Tomcat 才生效。开发阶段建议在conf/context.xml中添加Context antiResourceLockingfalse /实现热更新。4.2HTTP Status 500的核心日志定位策略500 错误表示 Servlet 执行抛出未捕获异常。关键日志不在catalina.out而在logs/localhost.date.log# Linux/Mac 下快速定位最新错误 tail -n 50 logs/localhost.date %Y-%m-%d.log | grep -A 5 -B 5 Exception常见 500 场景及日志特征ClassNotFoundException: com.mysql.jdbc.Driver→ 日志关键词java.lang.ClassNotFoundException→ 修复确认mysql-connector-java-5.1.47.jar在WEB-INF/lib/下且文件未损坏用jar -tf xxx.jar \| head -n 5检查SQLException: Access denied for user rootlocalhost→ 日志关键词java.sql.SQLException: Access denied→ 修复检查BaseDAO.java中的USER和PASSWORD是否与 MySQL 实际账号一致MySQL 5.7 默认root只允许localhost连接需执行CREATE USER root% IDENTIFIED BY 123456; GRANT ALL PRIVILEGES ON *.* TO root%; FLUSH PRIVILEGES;NullPointerException在ScoreDAO.addScore()第 42 行→ 日志关键词java.lang.NullPointerException 行号→ 修复该行通常是pstmt.executeUpdate()前未pstmt conn.prepareStatement(sql)检查 Connection 是否为 null即getConnection()失败未处理4.3 MySQL 数据库初始化脚本与字符集强制统一系统首次运行前必须执行建库建表 SQL。以下脚本确保 UTF-8 全链路-- 创建数据库显式指定字符集 CREATE DATABASE IF NOT EXISTS school_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- 切换数据库 USE school_db; -- 创建成绩表 CREATE TABLE t_score ( id BIGINT PRIMARY KEY AUTO_INCREMENT, student_id VARCHAR(20) NOT NULL COMMENT 学号, student_name VARCHAR(50) NOT NULL COMMENT 姓名, course_name VARCHAR(100) NOT NULL COMMENT 课程名, score DOUBLE NOT NULL COMMENT 成绩, create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT 录入时间 ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_unicode_ci; -- 插入测试数据 INSERT INTO t_score (student_id, student_name, course_name, score) VALUES (2021001, 张三, Java程序设计, 92.5), (2021002, 李四, 数据库原理, 87.0), (2021003, 王五, Web前端开发, 95.0);utf8mb4替代utf8MySQL 的utf8实际是utf8mb3不支持 emoji 和部分生僻汉字utf8mb4才是真正的 UTF-8COLLATE utf8mb4_unicode_ci比utf8mb4_general_ci排序更准确支持多语言TIMESTAMP DEFAULT CURRENT_TIMESTAMP自动记录录入时间无需 Java 代码生成。5. 从 ZIP 包解压到可运行系统的六步标准化操作流程5.1 解压与目录结构调整的原子操作指令拿到基于Java的Web学生成绩管理系统.zip后禁止直接双击解压到桌面。必须按以下顺序执行# 步骤 1创建标准 Tomcat webapps 目录假设 Tomcat 安装在 /opt/tomcat mkdir -p /opt/tomcat/webapps/ROOT # 步骤 2解压 ZIP 到临时目录避免覆盖 unzip 基于Java的Web学生成绩管理系统.zip -d /tmp/score-system # 步骤 3检查解压后结构关键 ls -R /tmp/score-system | head -n 30 # 输出应包含/tmp/score-system/WEB-INF/web.xml、/tmp/score-system/score/list.jsp 等 # 步骤 4将内容复制到 ROOT不是移动保留源文件备查 cp -r /tmp/score-system/* /opt/tomcat/webapps/ROOT/ # 步骤 5验证 WEB-INF 结构 ls -l /opt/tomcat/webapps/ROOT/WEB-INF/{web.xml,lib,classes} # 必须看到 web.xml、lib/mysql-connector-java-5.1.47.jar、classes/com/example/servlet/LoginServlet.class # 步骤 6启动 Tomcat 并观察日志 /opt/tomcat/bin/startup.sh tail -f /opt/tomcat/logs/catalina.out | grep -E (deploy|ERROR)cp -r而非mv防止解压包结构异常导致 ROOT 目录被清空head -n 30限制输出避免长列表刷屏聚焦关键路径grep -E同时监控部署与错误deploy表示成功ERROR表示失败二者同时跟踪效率最高。5.2 数据库连接测试的三行命令验证法在 Java 代码修改前先用命令行验证 MySQL 连通性# 1. 登录 MySQL用项目配置的账号密码 mysql -h localhost -u root -p123456 # 2. 选择数据库并查表确认表存在且有数据 USE school_db; SELECT COUNT(*) FROM t_score; # 3. 退出后用 telnet 测试端口排除防火墙问题 telnet localhost 3306 # 若显示 Connected to localhost. 则端口通若超时则检查 MySQL 是否启动、bind-address 是否为 127.0.0.1mysql -u root -p123456中-p后无空格密码紧贴-p否则会被当作数据库名telnet是最轻量的端口探测工具比nc更通用Windows/Linux/macOS 均自带。5.3 登录功能绕过与测试账号注入技巧开发阶段常需跳过登录直接进入主页面。两种安全做法方法一临时修改index.jsp重定向目标!-- 将原 index.jsp 中的 response.sendRedirect(login.jsp); -- !-- 改为 -- % // 开发模式自动登录 admin 用户 session.setAttribute(user, admin); response.sendRedirect(main.jsp); %方法二在LoginServlet中硬编码测试账号// 在 LoginServlet.doPost() 开头添加 if (admin.equals(username) 123456.equals(password)) { session.setAttribute(user, username); response.sendRedirect(main.jsp); return; } // 后续再执行原数据库校验逻辑两种方法都需在上线前删除仅用于本地调试避免代码泄露测试凭证session.setAttribute(user, ...)是登录态核心后续所有 Servlet 通过request.getSession().getAttribute(user)判断是否已登录。5.4 成绩导出功能的浏览器兼容性验证清单导出 Excel 功能在不同浏览器表现不一需逐一验证浏览器验证项通过标准Chrome 120点击导出按钮弹出下载对话框文件名为学生成绩表.xls无乱码Firefox 115下载后双击打开Excel 正常显示表头与数据时间列格式为2023-10-01 14:30:22Edge 120导出含中文的记录如“张三”“Java程序设计”单元格内中文显示完整无方块或问号Safari 16在 macOS 上下载文件保存成功Spotlight 可搜索到文件内容Safari 对Content-Disposition处理较严格若文件名乱码改用response.setHeader(Content-Disposition, attachment; filename\学生成绩表.xls\);用英文引号包裹Excel 2003 兼容性测试用 WPS 或 LibreOffice 打开.xls确认公式、样式无丢失。本文还有配套的精品资源点击获取
返回列表