
简介基于JspServlet实现的Web成绩管理系统面向JavaWeb初学者及课程设计人群覆盖学生、教师、管理员三类角色的核心业务适合作为SSM/JSP阶段课设参考或毕设改造底稿。压缩包共870个文件约39.64MB包含93个Java源码、46个JSP页面、174个CSS样式、212个JS脚本及9个Excel数据文件另有SQL脚本与说明文档基本能支撑部署运行和二次开发。系统按学生、教师、管理员三模块组织学生可查询个人信息与本人成绩教师可完成成绩录入、修改、查看与分析管理员可对学生、教师、班级、课程进行增删改查并可安排课程、分配班级、管理系统用户。已有173人学习下载适合需要完整可运行课设源码、模块化三层结构以及前后端资源对照参考的读者。1. 基于 JSP Servlet 的成绩管理系统课程设计是怎么把三个角色塞进一个 Web 项目的如果你是 Java Web 方向的学生十有八九会被布置一个“学生成绩管理系统”的课设。这个题目看起来常规但真正动手时才会发现学生、教师、管理员三个角色要复用同一套登录入口权限控制要区分页面级别和按钮级别成绩录入要考虑分数边界和课程关联单独写十个 JSP 页面也能交差但答辩时导师一问“你的 Servlet 是怎么分发请求的”就可能卡壳。我拆的这个项目是编号 100010041 的 JSPServletMySQL 成绩管理系统核心价值在于它把课程设计里最难的部分——学生模块、教师模块、管理员模块的三方协作做成了可以直接照抄的工程结构。适合正在做课设、或者想弄懂 JSP 传统开发方式非 Spring 系的读者拿来改改就能用自己的数据库跑起来。2. 项目架构与运行环境从三层结构到本地部署先把骨架看清2.1 技术选型为什么 2025 年还要看 JSP Servlet 项目现在企业里新项目基本是 Spring Boot 的天下但高校课设和部分老系统维护仍然大量使用 JSP Servlet。这个项目恰好是一个标准的 Java Web 应用JSP 负责视图层Servlet 负责控制器层DAO 负责数据访问层MySQL 存数据。三层结构清晰导师喜欢看这种分层因为能讲清楚“请求怎么走”。从源码包的静态资源可以看出项目引入了 Bootstrap 和 Summernotebootstrap.min.css 是前端样式框架用于页面布局和表格美化summernote-bs3.css 是一个富文本编辑器插件对应版本是 Bootstrap 3 适配版。这说明系统不是纯 JSP 裸写页面而是用前端框架把界面做了基础优化。常见的课设项目里用 Bootstrap 3 搭配 JSP 是很经典的组合因为不需要额外配置 Node 环境直接把 CSS 文件丢进 webapp 目录下就能用。项目本身是标准的 Maven 或 Dynamic Web Project 结构源码包中应该包含 srcJava 源码、webappJSP 页面和静态资源、pom.xml如果走 Maven或者 .classpath 等 Eclipse 工程文件。核心的运行环境需求如下组件版本建议说明JDK1.8 或 8老项目兼容性最好11 以上可能要调编译级别Tomcat8.5 / 9.0对应 Servlet 3.1/4.0适配 JSP 2.3MySQL5.7 或 8.0注意驱动包版本8.0 要用 mysql-connector-java 8.x开发工具Eclipse / IDEA配置好 Tomcat 运行时即可2.2 项目目录结构与请求流转一个登录请求是怎么走完的先看代码包里的核心目录结构拿到源码包后第一件事不是急着跑而是把目录对照一遍src/ ├── com/xxx/dao/ # 数据访问层StudentDao、TeacherDao、AdminDao ├── com/xxx/servlet/ # 控制器层LoginServlet、StudentServlet、ScoreServlet 等 ├── com/xxx/entity/ # 实体类Student、Teacher、Course、Score ├── com/xxx/util/ # 工具类DBUtil数据库连接、MD5Util密码加密 └── com/xxx/filter/ # 过滤器LoginFilter登录状态校验 webapp/ ├── css/ # bootstrap.min.css、style.min.css 等 ├── js/ # 前端脚本 ├── jsp/ # 学生页面、教师页面、管理员页面 └── WEB-INF/web.xml # 核心配置Servlet 映射和过滤器注册这里最值得看的是 web.xml 中的 Servlet 映射方式。老项目的常见写法是把所有请求按角色前缀分发例如/student/*交给 StudentServlet/teacher/*交给 TeacherServlet/admin/*交给 AdminServlet。这样做的优点是权限校验集中在过滤器中做每个角色只能访问自己前缀下的页面。我一般拿到源码后会先跑一遍登录逻辑搞清楚 Servlet 映射关系。以登录为例流程是用户提交表单 → LoginServlet 根据用户名和密码查询用户表 → 查出用户角色字段role→ 重定向到不同角色的首页。这个过程中请求会先经过 LoginFilter如果 session 里没有登录标记直接拦截跳回登录页。2.3 部署步骤从源码包到浏览器跑起来这是整个课设能否验收的第一步本地跑不起来后面全是空谈。我用 Eclipse或者 IDEA按下面的顺序操作第一步导入项目IDEA 选择 File → New → Project from Existing Sources选中源码包根目录如果是 Maven 项目会自动识别 pom.xml如果是普通 Web 项目选择 Web 目录即可。Eclipse 则用 Import → Existing Projects into Workspace注意勾选“Copy projects into workspace”避免源文件被外部改动影响。第二步配置 Tomcat在 IDEA 里打开 Run → Edit Configurations新增 Tomcat Server → Local。配置 Application server 指向本地 Tomcat 安装目录然后在 Deployment 页签点 选择该项目的 ArtifactApplication context 填/score或源码包里 web.xml 定义的 context注意看项目里有没有 context root 配置。第三步初始化数据库启动前必须把 SQL 脚本导入 MySQL。源码包里通常有一个database.sql或score.sql文件里面包含建库和插入初始数据的语句。用命令行导入mysql -u root -p database.sql如果源码包没给 SQL 文件就需要自己根据 DAO 里的 SQL 反推表结构。不过这个项目比较完整一般在database或sql目录下能找到初始化脚本。导入后确认三件事数据库名、用户名、密码是否和 DBUtil.java 里配置的一致。第四步修改数据库连接配置DBUtil.java 里的连接串是这个项目的生命线最常见的跑不起来就死在连接串上// com/xxx/util/DBUtil.java private static final String URL jdbc:mysql://localhost:3306/score_db?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/Shanghai; private static final String USER root; private static final String PASSWORD 123456;注意 JDK 8 配 MySQL 8.0 时serverTimezone参数必须加上否则报时区错误useSSLfalse是避免 MySQL 8.0 默认 SSL 认证导致的连接警告。密码改为你自己的本地数据库密码。改完后重新编译再启动 Tomcat访问http://localhost:8080/score/login.jsp应该能看到登录页。3. 数据库设计与初始化数据三张核心表怎么支撑三个角色的权限体系3.1 表结构拆解用户-角色-业务数据的分离方式打开 SQL 文件后整个系统的数据库设计思路会清晰很多。大多数课设版本采用这样的核心表结构用户表user、学生表student、教师表teacher、课程表course、成绩表score。其中 user 表存登录凭据和角色标识而 student 表和 teacher 表存业务扩展信息。我拆的这个版本关键点在于用户表与业务表是分离的还是合一的。如果合一比如 student 表直接带 password 字段登录逻辑会比较简单如果分离则登录后还要根据角色去查对应业务表获取姓名、班级等信息。建议拿到源码后先看 LoginServlet 的查询逻辑这决定了你改密码逻辑的复杂程度。-- 用户表只负责登录和角色识别 CREATE TABLE user ( uid int(11) NOT NULL AUTO_INCREMENT, username varchar(20) NOT NULL, password varchar(64) NOT NULL, role varchar(10) NOT NULL COMMENT admin / teacher / student, PRIMARY KEY (uid) ); -- 学生表业务扩展信息 CREATE TABLE student ( sid int(11) NOT NULL, name varchar(20) NOT NULL, class_id int(11) NOT NULL, gender varchar(4) DEFAULT NULL, PRIMARY KEY (sid) );3.2 初始化数据与测试账号三分钟跑通全功能导入 SQL 文件后通常里面会带几个初始账号。管理员账号一般是 admin/admin123 或 admin/123456教师账号类似 t001/123456学生账号类似 s001/123456。但不同版本的源码初始账号可能不同最稳妥的办法是直接查 user 表SELECT username, password, role FROM user;如果发现密码字段是加密后的 MD5 字符串自己又不知道原始密码有个小技巧先把已知的明文密码的 MD5 值算出来然后 UPDATE 上去。UPDATE user SET password e10adc3949ba59abbe56e057f20f883e WHERE username admin;这是123456的 MD5 值很多课设版密码验证就是用 DigestUtils.md5Hex 或自己实现的 MD5 工具。改完后再用 admin/123456 登录百试百灵。如果登录还是失败那就要看 LoginServlet 里密码比对逻辑是纯字符串相等还是加密后比对。我在拆这个项目时发现一个容易忽略的设计教师账号除了在 user 表里有记录还会在 teacher 表里对应一条业务记录两边的 uid 需要一致。管理员在后台修改教师信息时实际上要同步更新两张表这是事务操作的典型场景。3.3 成绩表的关键设计课程与学生的多对多关系成绩表在课设项目里是业务核心通常这样建CREATE TABLE score ( id int(11) NOT NULL AUTO_INCREMENT, student_id int(11) NOT NULL, course_id int(11) NOT NULL, score decimal(5,2) DEFAULT NULL, term varchar(20) DEFAULT NULL COMMENT 学期如 2024-2025-1, PRIMARY KEY (id), UNIQUE KEY uk_stu_course (student_id, course_id) );这里最值得借鉴的是UNIQUE KEY约束——同一个学生同一门课只能有一条成绩记录防止教师在录入时重复插入导致数据混乱。教师录入成绩时前端会先按学生列表加载界面提交到服务端后先判断是否已存在记录存在则执行 UPDATE不存在则 INSERT这就是常见的 insert-or-update 逻辑。4. 核心功能实现拆解登录过滤器、成绩录入与角色分发4.1 登录过滤器权限控制的第一道防线这个项目最值得看的功能点之一是过滤器。登录校验不放在每个 Servlet 里重复写而是抽成一个 LoginFilter对所有/jsp/*路径做拦截// com/xxx/filter/LoginFilter.java public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest request (HttpServletRequest) req; HttpServletResponse response (HttpServletResponse) resp; HttpSession session request.getSession(false); // 判断是否已登录 if (session null || session.getAttribute(user) null) { // 未登录则跳转登录页注意用绝对路径 response.sendRedirect(request.getContextPath() /login.jsp); return; } chain.doFilter(request, response); }这段代码逻辑很直白但有几个细节容易翻车getSession(false)表示不主动创建 session如果用户根本没登录过返回 null直接拦截request.getContextPath()必须拼上否则在非根路径部署时跳转地址会 404放行时调用chain.doFilter()不能丢。很多改版项目的登录失效问题都出在这三个细节上。4.2 教师录入成绩核心业务流的页面与 Servlet 协作教师模块最核心的功能是成绩录入。前端页面通常是三联动下拉框先选班级再选课程然后列出该班选该课的所有学生最后逐个输入分数。这种联动可以用 AJAX 实现也可以用最简单的表单回传方式实现。老派但好用的做法是页面 A选择班级和课程提交到 ScoreServletServlet 查询出学生列表后请求转发到录入页面 B页面 B 在 JSP 中用 JSTL 循环渲染学生表格!-- 录入页面中的核心片段 -- form actionScoreServlet?actionaddScore methodpost table c:forEach items${studentList} varstu tr td${stu.name}/td td input typehidden namestudentId value${stu.sid} input typenumber namescore min0 max100 required /td /tr /c:forEach /table input typehidden namecourseId value${courseId} button typesubmit批量提交/button /form这里有一个坑每个学生的 input 输入框用循环渲染后name 属性重复了服务端接收时要用request.getParameterValues(score)拿到数组再按顺序取出和 studentId 一一对应。// ScoreServlet 中的核心逻辑 String[] studentIds request.getParameterValues(studentId); String[] scores request.getParameterValues(score); for (int i 0; i studentIds.length; i) { int sid Integer.parseInt(studentIds[i]); double scoreVal Double.parseDouble(scores[i]); // 先查是否已有记录有则 update无则 insert boolean exists scoreDao.exists(sid, courseId); if (exists) { scoreDao.updateScore(sid, courseId, scoreVal); } else { scoreDao.addScore(sid, courseId, scoreVal); } }参数说明actionaddScore是 Servlet 内部的分发参数同一个 Servlet 用 action 区分“查询成绩列表”“录入成绩”“修改成绩”三种操作min0 max100是前端校验但服务端必须再校验一次因为绕过前端直接 POST 也能提交非法分数。我在实际改这个项目时习惯在 Service 层加一道分数范围判断不满足则抛异常回滚。4.3 管理员模块的增删改查三张关联表的删除顺序管理员的班级管理功能是课设答辩时导师喜欢追问的地方。删除一个班级不只是删 class 表里的记录还要处理班级下的学生。如果 student 表里 class_id 外键直接约束DELETE 会失败或报外键错误。常见的解决方案有两种第一种是物理删除前先查询该班有多少学生有学生则拒绝删除并提示“请先清空该班级学生”第二种是逻辑删除在班级表加一个 enabled 字段默认 1删除时改为 0查询时过滤enabled1。课设项目用第一种居多因为逻辑简单好解释。看这个项目的源码时可以看看班级删除逻辑里有没有处理这种关联数据如果没有答辩时正好可以当作一个改进点提出来。5. 避坑指南与常见问题排查课设运行中的五条血泪经验5.1 Tomcat 启动报 404但项目明明部署了现象访问http://localhost:8080/score/login.jsp直接 404Tomcat 控制台没有报错。原因最常发生的是 Application context 配置不对。IDEA 部署时默认 context 可能是/score_war_exploded而你访问的是/score路径对不上必然 404。另一类情况是 JSP 文件没放在 webapp 根目录下而是丢在了 src/main/webapp 的子目录里但路径写错。解决到 Run → Edit Configurations → Deployment 页签查看 Application context把访问路径改成与之完全一致。或者统一都用/再通过http://localhost:8080/login.jsp访问。提示改完 context 必须重启 Tomcat热部署有时不生效。5.2 数据库连接报 Access denied for user现象启动后页面能打开但一查数据就报错控制台输出Access denied for user rootlocalhost。原因DBUtil.java 中的密码和你本地 MySQL 实际密码不一致。很多人用的是 MySQL 8.0默认密码规则 caching_sha2_password 和 mysql-connector-java 5.x 驱动不兼容也会报认证失败。解决如果是密码问题改成自己的密码即可如果确认密码没写错还是失败看驱动包版本。mysql-connector-java 8.0.33 以上版本同时兼容 MySQL 5.7 和 8.0建议直接用 8.x 驱动然后把 URL 中的useSSLfalseserverTimezoneAsia/Shanghai补全。5.3 页面中文乱码表单提交后数据变成问号现象登录页中文正常但提交数据后页面显示乱码或者从数据库查出来的中文变成???。原因三处编码不一致——JSP 页面编码、Servlet 请求编码、数据库连接串编码。最常见的是一处漏了 UTF-8。解决按三层检查。JSP 文件顶部确保有% page contentTypetext/html;charsetUTF-8 languagejava %Servlet 里开始处加上request.setCharacterEncoding(UTF-8)数据库连接串确认带characterEncodingutf8。改完重启后再测。注意Tomcat 8.5 默认请求编码是 UTF-8高版本 Tomcat 一般不需要额外配置但加了肯定没错。5.4 成绩录入发现学生下拉框为空或数据错位现象教师选班级后学生列表加载不出来或者全班只有一个学生的数据重复显示。原因SQL 查询条件写错常见的是只查了 student 表没关联 class 表把全年级学生都查出来了或者下拉框的 value 绑定的是学生名称而非学生 ID导致提交后 ID 乱套。解决检查学生列表的 SQL确认带WHERE class_id ?条件前端下拉框的 option value 绑定stu.sid显示文本绑定stu.name。这里最容易翻车的确实是 ID 没有正确绑定导致后端拿到的一串 ID 全是姓名。5.5 管理员删课时把成绩也删没了现象删一门课程后教师查看成绩分析时发现该课程历史成绩消失。原因score 表对 course_id 有外键级联删除或者删除课程时手动执行了DELETE FROM score WHERE course_id...。如果是课设验收阶段这不算错但答辩时导师会问“成绩有保留价值为什么删课要连带删成绩”。解决建议改成逻辑删除course 表加 enabled 字段教师端查成绩只查enabled1的课程或者删除课程前弹窗提醒“该课程存在 N 条成绩记录确认删除吗”用户确认后在业务层先删成绩再删课程。这个改造不需要动表结构只改 Service 层的删除逻辑即可。6. 进阶用法在课程设计基础上加一个成绩分析页答辩时多一个亮点如果时间充裕我强烈建议在做完基本功能后加一个“课程成绩分析”页面。这是导师最喜欢看到的设计点因为它把 CRUD 变成了一个带有统计分析功能的模块显示了你对 SELECT 聚合函数的掌握。实现思路很简单按课程统计最高分、最低分、平均分、及格率用一条 SQL 搞定SELECT c.cname, MAX(s.score) AS max_score, MIN(s.score) AS min_score, AVG(s.score) AS avg_score, SUM(CASE WHEN s.score 60 THEN 1 ELSE 0 END) / COUNT(*) * 100 AS pass_rate FROM score s JOIN course c ON s.course_id c.cid WHERE s.course_id 2 GROUP BY c.cname;这条 SQL 里有几个点可以在答辩时展开CASE WHEN条件计数是统计及格率的标准写法AVG()默认返回小数如果需要四舍五入用ROUND(AVG(score), 1)。在 ScoreServlet 里加一个actionanalyze的分支把 query 结果放进 request 域转发到新 JSP 页面展示// ScoreServlet 中新增的 analyze 分支 double avgScore resultMap.get(avg_score) ! null ? ((Number) resultMap.get(avg_score)).doubleValue() : 0.0; request.setAttribute(avgScore, Math.round(avgScore * 10) / 10.0); request.setAttribute(passRate, Math.round((Double) resultMap.get(pass_rate) * 100) / 100.0); request.getRequestDispatcher(/jsp/teacher/scoreAnalyze.jsp).forward(request, response);页面端可以配合一个极简的柱状图——不用引入 ECharts直接用 div 宽度模拟柱子纯 CSS 输出排名前五的学生分数对比。这样做的好处是整个功能只依赖 JSP 和 CSS不增加任何额外 jar 包但视觉效果好答辩时有话说!-- 及格率可视化一个简易横向进度条 -- div classprogress div classprogress-bar stylewidth: ${passRate}%; 及格率 ${passRate}% /div /div如果想把可视化做得更完整一些对每门课的成绩分段统计90-100、80-89、70-79、60-69、0-59再配一个表格基本就是一个完整的“学生学习质量分析”模块了。导师常见的追问是“这个分析有什么实际用处”回答方向是院系可以根据课程平均分评估教学效果辅导员可以根据及格率锁定重点帮扶班级比单纯看成绩列表直观得多。从那以后我再做类似课设项目都会先花 15 分钟把 SQL 里的聚合查询梳理一遍确认字段名、关联键、空值处理再动手写页面。这套项目的价值不完全在于代码本身而在于它把 JSP Servlet MySQL 的完整链路演示清楚了——你拿到它之后顺着登录过滤器往下追整个请求流转就刻在脑子里了。希望帮到你。本文还有配套的精品资源点击获取