
简介这是一套面向Java Web初学者与课程设计者的网上学生成绩管理系统完整源码包基于Java、MySQL与JSP技术栈实现涵盖用户登录认证、成绩录入、查询、修改与删除等核心业务适合用作毕业设计、课程大作业或Web开发入门练手项目。压缩包共301个文件约20.31MB其中scss与css负责页面样式jpg、png、svg等为界面素材java、class与jar构成后端逻辑与依赖jsp承担视图展示sql文件提供数据库脚本另附论文文档与项目说明目录结构清晰便于按模块阅读与二次开发。资源已积累1166人学习下载读者可从中获取完整的项目分层结构、Servlet与JDBC交互范例、数据库建表脚本以及论文参考帮助快速理解Java Web开发流程并完成自己的成绩管理类系统。1. 从一份 JSP 成绩管理源码说起为什么它至今仍是课程设计的高频选题每年毕业季总有一批同学在选题系统里反复刷新最后落点往往就是「基于 JavaMySQLJSP 的学生成绩管理系统」。原因不复杂技术栈成熟、资料多、导师熟悉、答辩时不容易被问穿。但真正动手时很多人卡在第一步——环境跑不起来Tomcat 一启动就报 404数据库连不上JSP 页面中文乱码。这套源码的价值不在于它有多先进而在于它把 Java Web 最核心的链路——请求、会话、数据库、页面渲染——完整串了一遍。如果你正在找一份能跑通、能改、能写进论文的 Java Web 项目或者想用 JSP 理解 MVC 的原始形态这篇笔记会从环境搭建、数据库设计、核心功能实现到避坑排查把这条路走一遍。JSP 不是过时技术它是理解 Servlet 容器行为最直接的入口而 MySQL 则是这套系统里最容易被忽视却最影响稳定性的环节。2. 环境搭建与项目导入把源码跑起来的最小闭环2.1 JDK、Tomcat、MySQL 的版本匹配逻辑很多人拿到源码后第一反应是装最新版 JDK 和 MySQL结果项目跑不起来。JSP 项目对版本敏感尤其是 Servlet API 和 JDBC 驱动。常见做法是JDK 用 8 或 11Tomcat 用 8.5 或 9MySQL 用 5.7 或 8.0。为什么不是 JDK 17因为老项目里的 JSP 页面可能用了javax.servlet而不是jakarta.servletTomcat 10 之后包名变了直接 404。MySQL 8.0 的驱动类名是com.mysql.cj.jdbc.Driver5.7 是com.mysql.jdbc.Driver连接串还要加时区和 SSL 参数。这些细节不匹配项目连启动都做不到。安装 MySQL 时Windows 10 上推荐用 MSI 安装包勾选 MySQL Server 和 MySQL Workbench。安装过程中设置 root 密码字符集选utf8mb4。安装完成后用命令行验证mysql -u root -p # 输入密码后执行 SHOW VARIABLES LIKE character_set%;如果character_set_server不是utf8mb4后面 JSP 页面插入中文会变成问号。修改my.ini或my.cnf在[mysqld]下加character-set-serverutf8mb4重启 MySQL 服务。Tomcat 下载解压后把项目里的web目录或WebContent目录复制到tomcat/webapps/下或者直接在 IDE 里配置 Tomcat 服务器。Eclipse 需要装 Java EE 版本IntelliJ IDEA 社区版没有 Tomcat 集成得用 Ultimate 或者手动配置。这一步的坑在于IDE 里配置的 Tomcat 和独立启动的 Tomcat 可能用的不是同一个 JDK导致Unsupported major.minor version错误。2.2 导入源码后必须改的四个配置点源码导入 IDE 后不能直接点运行。先检查这四个地方第一数据库连接配置。通常在src/db/DBUtil.java或src/com/util/DBHelper.java里找到url、username、password。改成你本地 MySQL 的地址和密码。如果是 MySQL 8.0URL 要写成String url jdbc:mysql://localhost:3306/student_score?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/ShanghaiuseSSLfalse;serverTimezone不写会报The server time zone value ?D1ú±ê×?ê±?? is unrecognized这是 MySQL 8.0 驱动强制要求。第二JDBC 驱动 jar 包。源码里可能带了mysql-connector-java-5.1.x.jar如果你本地是 MySQL 8.0要换成mysql-connector-java-8.0.x.jar放到WEB-INF/lib下并在 IDE 的 Build Path 里确认引用。第三web.xml 里的 Servlet 版本。老项目可能是 2.5 或 3.0Tomcat 9 支持Tomcat 10 不认。如果报ClassNotFoundException: javax.servlet.http.HttpServlet就是这个问题。第四项目编码。JSP 页面顶部要有% page contentTypetext/html;charsetUTF-8 languagejava %Java 文件里如果有中文注释IDE 要设置成 UTF-8。否则编译时中文注释会报错。改完这四点启动 Tomcat访问http://localhost:8080/项目名/login.jsp应该能看到登录页。如果 404检查web.xml里的welcome-file和实际文件名是否一致。2.3 数据库建表与初始数据导入源码里一般会带一个.sql文件用 Navicat 或命令行导入。常见表结构包括student学生信息、teacher教师信息、course课程、score成绩、user登录账号。导入前先建库CREATE DATABASE student_score DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE student_score; SOURCE /path/to/student_score.sql;导入后检查表里有没有数据。如果没有登录页的账号密码可能来自user表需要手动插入一条INSERT INTO user (username, password, role) VALUES (admin, 123456, admin);密码如果是明文登录就能过如果是 MD5得用MD5(123456)插入。这一步的坑是有些源码的 SQL 文件用了utf8而不是utf8mb4导入后中文乱码需要把 SQL 文件用文本编辑器打开另存为 UTF-8 无 BOM 格式再重新导入。3. 核心功能拆解从登录到成绩录入的完整链路3.1 登录模块Session 与过滤器怎么配合JSP 项目的登录逻辑很直接login.jsp提交表单到LoginServletServlet 查数据库匹配成功就把用户信息放进HttpSession然后重定向到main.jsp。关键代码// LoginServlet.java String username request.getParameter(username); String password request.getParameter(password); User user userDao.findByUsernameAndPassword(username, password); if (user ! null) { HttpSession session request.getSession(); session.setAttribute(currentUser, user); response.sendRedirect(main.jsp); } else { request.setAttribute(msg, 用户名或密码错误); request.getRequestDispatcher(login.jsp).forward(request, response); }逻辑说明findByUsernameAndPassword里用PreparedStatement防 SQL 注入不要用字符串拼接。session.setAttribute把用户对象存进去后续页面用session.getAttribute(currentUser)判断是否登录。参数说明request.getParameter拿的是表单字段名要和 JSP 里的name属性一致。但光有登录不够还得防止未登录直接访问main.jsp。常见做法是加一个LoginFilter// LoginFilter.java public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest request (HttpServletRequest) req; HttpServletResponse response (HttpServletResponse) resp; String uri request.getRequestURI(); if (uri.endsWith(login.jsp) || uri.endsWith(LoginServlet)) { chain.doFilter(req, resp); return; } HttpSession session request.getSession(); if (session.getAttribute(currentUser) null) { response.sendRedirect(login.jsp); return; } chain.doFilter(req, resp); }在web.xml里配置这个过滤器拦截/*。这样未登录用户访问任何页面都会被踢回登录页。坑在于过滤器里判断uri.endsWith时如果项目路径带上下文比如/student_score/main.jspendsWith(main.jsp)是成立的但如果是/student_score/score/list.jsp就得用contains或者更精确的匹配。3.2 成绩录入与查询JSP 页面如何绑定后端数据成绩录入页面通常是score_add.jsp表单提交到ScoreServletServlet 调用 DAO 插入数据。JSP 页面里用 EL 表达式和 JSTL 标签展示课程列表% taglib prefixc urihttp://java.sun.com/jsp/jstl/core % select namecourseId c:forEach items${courseList} varcourse option value${course.id}${course.name}/option /c:forEach /select${courseList}是 Servlet 里request.setAttribute(courseList, courseDao.findAll())传过来的。JSTL 的c:forEach遍历列表生成下拉选项。参数说明items是集合var是每次迭代的变量名value和${course.id}对应。成绩查询页面score_list.jsp用表格展示table trth学号/thth姓名/thth课程/thth分数/th/tr c:forEach items${scoreList} vars tr td${s.studentNo}/td td${s.studentName}/td td${s.courseName}/td td${s.score}/td /tr /c:forEach /table这里的数据来自ScoreServlet里的多表联查 SQLSELECT st.student_no, st.name AS student_name, c.name AS course_name, sc.score FROM score sc JOIN student st ON sc.student_id st.id JOIN course c ON sc.course_id c.id WHERE sc.student_id ?坑在于如果score表里存的是student_id和course_id而页面要显示学号和课程名就必须联查。有些源码为了省事直接在score表里冗余存了学号和课程名改数据时容易不一致。我一般会保留外键查询时联表。3.3 分页与排序MySQL LIMIT 和 ORDER BY 的配合成绩列表数据多了要分页。MySQL 用LIMIT offset, sizeoffset是起始行size是每页条数。比如第 2 页每页 10 条SELECT ... FROM score sc JOIN ... LIMIT 10, 10;Java 里计算offsetint page request.getParameter(page) null ? 1 : Integer.parseInt(request.getParameter(page)); int size 10; int offset (page - 1) * size; ListScore list scoreDao.findByPage(offset, size); int total scoreDao.countAll(); int totalPages (total size - 1) / size; request.setAttribute(scoreList, list); request.setAttribute(totalPages, totalPages); request.setAttribute(currentPage, page);排序用ORDER BY比如按分数降序ORDER BY sc.score DESC如果前端要点击表头切换排序得把排序字段和方向作为参数传进来但要注意防 SQL 注入——不能直接拼字段名要用白名单校验String sort request.getParameter(sort); if (!score.equals(sort) !student_no.equals(sort)) { sort score; } String order asc.equalsIgnoreCase(request.getParameter(order)) ? asc : desc; String sql SELECT ... ORDER BY sort order LIMIT ?, ?;这里sort和order虽然拼进 SQL但已经过白名单过滤不是用户输入什么就拼什么。这是 JSP 项目里最容易翻车的地方之一。4. 避坑与排查JSPMySQL 项目最常见的五类翻车现场4.1 中文乱码从数据库到页面的全链路排查现象登录页输入中文用户名提交后变成???或者成绩列表里的姓名显示乱码。原因编码不一致。MySQL 服务端字符集、数据库字符集、表字符集、JDBC 连接串、JSP 页面编码、Tomcat 的URIEncoding任何一环不是 UTF-8 都会乱。解决按顺序检查。第一MySQL 里SHOW VARIABLES LIKE character_set%确保character_set_server和character_set_database是utf8mb4。第二JDBC URL 加useUnicodetruecharacterEncodingutf8。第三JSP 页面顶部% page contentTypetext/html;charsetUTF-8 %。第四Tomcat 的server.xml里Connector加URIEncodingUTF-8。第五如果用了request.setCharacterEncoding(UTF-8)要在所有getParameter之前调用。这五步走完乱码基本消失。4.2 数据库连接池耗尽Too many connections 怎么调现象项目跑一段时间后报Too many connections或者页面卡死。原因每次请求都DriverManager.getConnection没有关闭连接或者连接池配置太小。解决用连接池比如 Druid 或 C3P0。如果源码里是手写连接至少要在finally里close()。连接池配置示例# druid.properties driverClassNamecom.mysql.cj.jdbc.Driver urljdbc:mysql://localhost:3306/student_score?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/ShanghaiuseSSLfalse usernameroot password123456 initialSize5 maxActive20 maxWait60000maxActive是最大连接数maxWait是获取连接的超时时间。如果并发不高20 够用。坑在于连接池的removeAbandoned如果开启可能会误杀正在用的连接一般不建议开。4.3 JSP 页面报 500空指针与类型转换的常见位置现象访问某个页面报java.lang.NullPointerException或NumberFormatException。原因session.getAttribute(currentUser)返回 null 后直接调方法或者Integer.parseInt(request.getParameter(id))时参数为空。解决加判空。比如User user (User) session.getAttribute(currentUser); if (user null) { response.sendRedirect(login.jsp); return; }对于parseInt用 try-catch 或者先判断String idStr request.getParameter(id); if (idStr null || idStr.trim().isEmpty()) { response.sendRedirect(error.jsp); return; } int id Integer.parseInt(idStr);坑在于有些源码在 JSP 里直接写%request.getParameter(name).toUpperCase()%参数为空就 500。JSP 里尽量用 EL 表达式它遇到 null 会输出空字符串不会抛异常。4.4 Tomcat 启动报 ClassNotFoundException驱动和 jar 包放哪现象Tomcat 启动时控制台报ClassNotFoundException: com.mysql.cj.jdbc.Driver。原因JDBC 驱动 jar 没放到WEB-INF/lib下或者 IDE 的部署配置里没包含。解决把mysql-connector-java-8.0.x.jar复制到web/WEB-INF/lib目录。在 Eclipse 里右键项目 → Properties → Deployment Assembly确保WebContent/WEB-INF/lib被映射到/WEB-INF/lib。在 IDEA 里Project Structure → Artifacts → 确认WEB-INF/lib下有这个 jar。如果用的是 Maven在pom.xml里加依赖scope 用provided还是compile要看 Tomcat 是否自带——Tomcat 不带 MySQL 驱动所以用compile。4.5 页面跳转 404路径到底该写相对还是绝对现象登录成功后response.sendRedirect(main.jsp)跳转 404。原因sendRedirect是相对于当前请求的 URL如果当前 URL 是/student_score/LoginServlet重定向到main.jsp会变成/student_score/main.jsp但如果项目上下文不是/student_score就找不到。解决用request.getContextPath()拼绝对路径response.sendRedirect(request.getContextPath() /main.jsp);在 JSP 里链接也用c:url value/main.jsp/或者${pageContext.request.contextPath}/main.jsp。坑在于forward和redirect的路径规则不一样forward是服务器内部跳转路径相对于当前页面redirect是浏览器重新请求路径相对于站点根。搞混了就会 404。5. 论文写作与源码改造让这套系统通过答辩的进阶技巧5.1 论文里该写什么从功能列表到技术选型论证很多同学论文写成了操作手册第一章绪论第二章需求分析第三章总体设计第四章详细设计第五章测试。但答辩老师最想看到的是你为什么选 JSP 而不是 Spring Boot为什么用 MySQL 而不是 SQL Server这部分要写出技术选型的理由。比如JSP 适合中小型项目开发速度快与 Servlet 无缝集成MySQL 开源免费社区活跃适合课程设计预算。不要写「因为简单所以选」要写「在项目规模、开发周期、团队技术栈约束下JSPMySQL 的投入产出比最高」。数据库设计部分把 E-R 图放上去然后解释为什么score表要拆成student_id和course_id两个外键而不是直接存学号和课程名。这是范式设计的体现也是答辩时容易被问的点。测试部分不要只写「功能正常」要写具体测试用例输入错误密码、输入超长用户名、并发插入成绩观察系统行为。5.2 源码改造加一个「成绩导出 Excel」功能如果想让项目更有亮点可以加一个导出 Excel 的功能。用 Apache POI 库在ScoreServlet里加一个export方法// 导出 Excel HSSFWorkbook workbook new HSSFWorkbook(); HSSFSheet sheet workbook.createSheet(成绩表); HSSFRow header sheet.createRow(0); header.createCell(0).setCellValue(学号); header.createCell(1).setCellValue(姓名); header.createCell(2).setCellValue(课程); header.createCell(3).setCellValue(分数); ListScore list scoreDao.findAll(); int rowNum 1; for (Score s : list) { HSSFRow row sheet.createRow(rowNum); row.createCell(0).setCellValue(s.getStudentNo()); row.createCell(1).setCellValue(s.getStudentName()); row.createCell(2).setCellValue(s.getCourseName()); row.createCell(3).setCellValue(s.getScore()); } response.setContentType(application/vnd.ms-excel); response.setHeader(Content-Disposition, attachment;filenamescores.xls); workbook.write(response.getOutputStream()); workbook.close();逻辑说明HSSFWorkbook是 POI 对.xls格式的实现XSSFWorkbook对应.xlsx。response.setHeader告诉浏览器这是下载文件不是直接打开。参数说明Content-Disposition的filename如果带中文要 URL 编码否则文件名乱码。这个功能加进去论文里可以写「数据导出与报表生成」比单纯增删改查更有说服力。5.3 答辩前必须自己走一遍的检查清单答辩前一周把项目重新部署一遍用干净的环境。检查这几项第一数据库脚本能不能从零导入不报错。第二登录、增删改查、分页、排序每个功能点手动点一遍。第三把 Tomcat 日志级别调到INFO看有没有异常堆栈。第四准备三个可能被问的问题为什么用 JSP 不用前后端分离数据库索引加在哪如果并发量上来怎么优化第五论文里的截图要和实际系统一致不要用网上的图。我自己的习惯是答辩前一天把项目打包成 war放到另一台电脑上部署模拟评委环境。有一次就是因为在本地跑得好好的换台机器 JDK 版本不对当场翻车。后来每次都用java -version和tomcat/bin/version.bat确认环境。这套 JSP 成绩管理系统虽然老但把 Java Web 的底子打牢了后面学 Spring Boot 会顺很多。希望帮到你。本文还有配套的精品资源点击获取