简介:这份资源是基于JSP与MySQL开发的学生信息管理系统完整源码包,面向正在学习Java Web、准备课程设计或毕业设计的初学者与中级开发者,帮助其理解三层架构下角色权限与数据增删改查的实现思路。系统划分学生、教师、管理员三类角色:学生可修改个人资料并按条件查询成绩,教师能录入修改成绩、查找学生信息与维护个人资料,管理员则负责学生与教师账号的增删改查及成绩查询,覆盖了典型教务管理场景的核心业务。压缩包共123个文件,约141KB,以86个java业务实现类与28个jsp页面为主体,另含少量png图片、md说明及配置文件,结构紧凑便于阅读与二次开发。目前已有249人学习下载,适合作为JSP+Servlet+MySQL整合练习的参考案例,读者可从中获取数据库连接、Servlet跳转、权限过滤与成绩统计等模块的落地写法,并据此快速搭建自己的课程设计项目。
1. 从一份 JSP 学生信息管理系统源码说起:它到底能跑出什么
如果你手头正好有一份JSP学生信息管理系统源码.zip,解压后看到ScoreImpl.java、StudentImpl.java、TeacherImpl.java、ClassesImpl.java、MajorImpl.java这一串文件,第一反应大概率是:这是个典型的 JavaWeb 课程设计项目,三层结构,JSP 做视图,Servlet 做控制,Impl 做业务实现,MySQL 存数据。它解决的不是高并发场景,而是「一个学校教务场景下,学生、教师、管理员三种角色各自该看到什么、能改什么」的问题。学生能改个人资料、按条件查自己的成绩;教师能录成绩、查学生、改自己资料;管理员能增删改查学生和教师、管理班级和专业。适合谁?适合正在做 JavaWeb 课程设计、想找一个结构完整、能跑通、能改的参考工程的人,也适合刚学完 JSP+Servlet+JDBC 想拿一个真实项目练手的人。它不新,但结构清楚,改起来不玄学。
2. 把工程跑起来:环境、数据库与三个角色的入口
2.1 环境选型:为什么是 JDK 8 + Tomcat 8 + MySQL 5.7
这份源码里的Impl类用的是 JDBC 直连,没有 Spring 那一套,所以环境不需要太新。常见做法是 JDK 8 配 Tomcat 8.5,MySQL 用 5.7 系列。原因很直接:JDK 8 对老版本 Tomcat 兼容最稳,MySQL 5.7 的驱动mysql-connector-java-5.1.x和源码里写的连接串格式匹配,换成 MySQL 8 要改驱动类名和 URL 参数,新手容易在这里翻车。
先确认三个东西的版本:
java -version # 期望输出:java version "1.8.0_xxx" mysql --version # 期望输出:mysql Ver 14.14 Distrib 5.7.xx # Tomcat 解压后进 bin 目录 ./startup.sh # Linux startup.bat # Windows逻辑说明:java -version看的是 JRE 版本,Tomcat 启动时会用它。MySQL 版本决定后面 JDBC URL 怎么写。Tomcat 启动脚本在bin目录下,Windows 用.bat,Linux 用.sh,这一步只是确认环境,不涉及项目配置。
参数说明:如果java -version显示 11 或 17,不是不能跑,但源码里如果有javax.servlet包引用,Tomcat 10 之后改成了jakarta.servlet,会直接编译报错。所以要么降 JDK,要么换 Tomcat 9 以下。
2.2 数据库导入:从 SQL 文件到连接串
源码包里一般会带一个.sql文件,常见命名是db_student.sql或student_manager.sql。先建库再导入:
mysql -u root -p -e "CREATE DATABASE student_db DEFAULT CHARACTER SET utf8mb4;" mysql -u root -p student_db < db_student.sql逻辑说明:第一条命令建库,指定utf8mb4是为了避免中文姓名和班级名乱码。第二条把 SQL 文件里的表结构和初始数据灌进去。导入完成后用SHOW TABLES;确认表数量,通常会有student、teacher、classes、major、score、privilege这几张。
参数说明:-u root是用户名,-p后面不跟密码,回车后手动输入,避免密码进命令历史。如果 SQL 文件里已经写了CREATE DATABASE,第一条可以跳过,直接导入。
接着改数据库连接配置。源码里连接信息一般写在src下的db.properties或某个DBUtil.java里:
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/student_db?useUnicode=true&characterEncoding=utf8 jdbc.username=root jdbc.password=你的密码逻辑说明:com.mysql.jdbc.Driver是 MySQL 5.x 的驱动类,MySQL 8 要改成com.mysql.cj.jdbc.Driver。URL 里的useUnicode和characterEncoding两个参数是中文不乱码的关键,少了它们,学生姓名查出来可能是问号。
参数说明:localhost:3306是本机默认端口,如果 MySQL 装在别的机器上要改 IP。student_db要和前面建的库名一致。
2.3 部署到 Tomcat 并验证三个角色入口
把工程打成 WAR 包,或者直接把 WebContent 目录拷到 Tomcat 的webapps下:
# 假设工程目录叫 StudentManager cp -r StudentManager /path/to/tomcat/webapps/ # 启动 Tomcat /path/to/tomcat/bin/startup.sh逻辑说明:Tomcat 启动时会自动解压并部署webapps下的工程。访问地址通常是http://localhost:8080/StudentManager/。登录页一般叫login.jsp,三种角色共用同一个登录入口,靠privilege字段区分跳转。
参数说明:如果 8080 被占用,改conf/server.xml里的Connector port。工程名要和访问路径一致,否则 404。
验证顺序建议:先用管理员账号登录,看能不能进学生列表;再用教师账号登录,看能不能查到学生成绩;最后用学生账号登录,看能不能改个人资料。三个角色都通了,说明数据库连接和权限判断没问题。
提示:如果登录后页面空白,先看 Tomcat 的
logs/catalina.out,大概率是 JDBC 驱动没放进WEB-INF/lib。
3. 源码结构拆解:Impl 类、Servlet 与 JSP 页面的分工
3.1 Impl 类到底在做什么:以 StudentImpl 和 ScoreImpl 为例
StudentImpl.java和ScoreImpl.java是业务实现类,通常实现一个对应的接口,里面封装了对student表和score表的增删改查。以StudentImpl为例,常见方法有addStudent、deleteStudent、updateStudent、queryStudentById、queryAllStudents。每个方法内部就是 JDBC 的PreparedStatement操作。
public boolean addStudent(Student student) { String sql = "INSERT INTO student(name, sex, age, classes_id, major_id) VALUES(?,?,?,?,?)"; try (Connection conn = DBUtil.getConnection(); PreparedStatement ps = conn.prepareStatement(sql)) { ps.setString(1, student.getName()); ps.setString(2, student.getSex()); ps.setInt(3, student.getAge()); ps.setInt(4, student.getClassesId()); ps.setInt(5, student.getMajorId()); return ps.executeUpdate() > 0; } catch (SQLException e) { e.printStackTrace(); return false; } }逻辑说明:PreparedStatement用占位符?传参,避免 SQL 注入。try-with-resources保证连接和语句自动关闭。executeUpdate返回受影响行数,大于 0 表示插入成功。
参数说明:classes_id和major_id是外键,插入前要确保classes和major表里有对应记录,否则会报外键约束错误。这是新手最容易踩的坑之一。
ScoreImpl.java类似,但多了一个按条件查询的方法,比如按学号、课程、学期组合查:
public List<Score> queryScoreByCondition(String studentNo, String subject, String term) { StringBuilder sql = new StringBuilder("SELECT * FROM score WHERE 1=1"); List<Object> params = new ArrayList<>(); if (studentNo != null && !studentNo.isEmpty()) { sql.append(" AND student_no = ?"); params.add(studentNo); } if (subject != null && !subject.isEmpty()) { sql.append(" AND subject = ?"); params.add(subject); } if (term != null && !term.isEmpty()) { sql.append(" AND term = ?"); params.add(term); } // 执行查询并映射结果集 return query(sql.toString(), params.toArray()); }逻辑说明:用StringBuilder拼 SQL,WHERE 1=1是常见技巧,后面每个条件都加AND,不用判断是不是第一个条件。参数放进List,最后转数组传给查询方法。
参数说明:studentNo、subject、term三个条件都是可选的,传空字符串或 null 就不参与过滤。这种写法比写三个重载方法更灵活,但要注意参数顺序和 SQL 里的?一一对应。
3.2 Servlet 层:ReportScoreServlet 和登录跳转
ReportScoreServlet.java从名字看是处理成绩上报的。典型流程是:教师在前端页面填成绩,提交到 Servlet,Servlet 调ScoreImpl的更新方法,然后重定向回成绩列表页。
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("UTF-8"); String studentNo = request.getParameter("studentNo"); String subject = request.getParameter("subject"); String score = request.getParameter("score"); Score s = new Score(); s.setStudentNo(studentNo); s.setSubject(subject); s.setScore(Double.parseDouble(score)); ScoreImpl scoreImpl = new ScoreImpl(); boolean ok = scoreImpl.updateScore(s); if (ok) { response.sendRedirect("scoreList.jsp"); } else { request.setAttribute("msg", "成绩更新失败"); request.getRequestDispatcher("scoreEdit.jsp").forward(request, response); } }逻辑说明:setCharacterEncoding("UTF-8")必须在取参数之前调用,否则中文课程名会乱码。sendRedirect是重定向,浏览器地址栏会变;forward是转发,地址栏不变。更新失败时留在原页面并带错误信息。
参数说明:studentNo、subject、score三个参数名要和前端表单的name属性一致。Double.parseDouble如果传了非数字会抛异常,实际项目里应该加 try-catch,但课程设计源码经常省略。
3.3 JSP 页面与 WdatePicker.js.bak 的作用
WdatePicker.js.bak这个文件后缀是.bak,说明它是备份文件,原文件应该是WdatePicker.js。这是一个日期选择器插件,用在需要选日期的输入框上,比如查成绩时选学期、录成绩时选考试日期。如果页面里引用了WdatePicker.js但文件只有.bak,日期控件会失效。
<input type="text" name="examDate" onclick="WdatePicker()" readonly> <script src="js/WdatePicker.js"></script>逻辑说明:onclick="WdatePicker()"绑定点击事件,弹出日期选择框。readonly防止手动输入非法日期。脚本引用路径要对,否则WdatePicker is not defined。
参数说明:如果只有.bak文件,把后缀改回.js即可。路径按实际工程目录调整,常见是WebContent/js/下。
注意:JSP 页面里如果用了
<jsp:include>或<%@ include %>,注意路径是相对路径还是绝对路径,混用容易导致样式或脚本加载失败。
4. 避坑与排查:这份源码最容易翻车的五个地方
4.1 中文乱码:从数据库到 JSP 页面全链路
现象:学生姓名、班级名显示为???或乱码。
原因:三个环节都可能出问题——数据库字符集不是utf8mb4、JDBC URL 没加characterEncoding=utf8、JSP 页面没写<%@ page contentType="text/html;charset=UTF-8" %>。
解决:先确认数据库和表的字符集,再检查 JDBC URL,最后看 JSP 头部。三处都改成 UTF-8 后重启 Tomcat。
4.2 外键约束报错:添加学生时提示 Cannot add or update a child row
现象:管理员添加学生,提交后报Cannot add or update a child row: a foreign key constraint fails。
原因:student表的classes_id或major_id在classes和major表里不存在。
解决:先往classes和major表里插几条基础数据,再添加学生。或者检查前端下拉框的值是不是从数据库查出来的,如果写死了但数据库里没有对应 ID,也会报这个错。
4.3 驱动类找不到:ClassNotFoundException: com.mysql.jdbc.Driver
现象:Tomcat 启动后访问登录页,后台报ClassNotFoundException。
原因:mysql-connector-java的 jar 包没放进WEB-INF/lib,或者只放进了项目的 Build Path 但没随 WAR 打包。
解决:把 jar 包复制到WebContent/WEB-INF/lib下,重新部署。如果用的是 Maven,确认pom.xml里依赖的 scope 不是provided。
4.4 日期控件不弹出:WdatePicker is not defined
现象:点击日期输入框没反应,控制台报WdatePicker is not defined。
原因:WdatePicker.js.bak是备份文件,实际引用的WdatePicker.js不存在。
解决:把.bak后缀去掉,或者从其他项目拷一份WdatePicker.js放进去。同时检查<script>标签的src路径是否正确。
4.5 登录后权限跳转错误:学生进了管理员页面
现象:用学生账号登录,却跳到了管理员的学生管理页面。
原因:登录 Servlet 里判断privilege字段的逻辑写错了,或者 session 里存的角色和页面判断的角色不一致。
解决:在登录成功后打印一下privilege的值,确认数据库里存的是什么。常见做法是1管理员、2教师、3学生,但不同源码可能不一样。然后检查跳转的if-else分支有没有写反。
5. 二次开发与验证:怎么改造成自己的课程设计
5.1 加一个「按班级查学生」的功能
现有源码里管理员能查所有学生,但按班级筛选可能没有。加这个功能要动三个地方:StudentImpl加方法、Servlet 加处理、JSP 加表单。
先在StudentImpl里加:
public List<Student> queryStudentsByClasses(int classesId) { String sql = "SELECT * FROM student WHERE classes_id = ?"; return query(sql, new Object[]{classesId}); }逻辑说明:复用已有的query方法,传入 SQL 和参数数组。返回List<Student>,上层拿到后塞进 request 再转发到 JSP。
参数说明:classesId从下拉框传过来,下拉框的选项从classes表查。
然后在 Servlet 里判断action参数:
String action = request.getParameter("action"); if ("queryByClasses".equals(action)) { int classesId = Integer.parseInt(request.getParameter("classesId")); List<Student> list = new StudentImpl().queryStudentsByClasses(classesId); request.setAttribute("studentList", list); request.getRequestDispatcher("studentList.jsp").forward(request, response); }逻辑说明:用一个action参数区分不同操作,是 JSP+Servlet 项目里常见的做法。比每个功能写一个 Servlet 更省事。
参数说明:classesId要做非空和数字格式校验,否则parseInt会抛异常。
5.2 验证改造是否成功:三个检查点
改完之后别急着说「好了」,按这个顺序验一遍:
| 检查点 | 操作 | 预期结果 |
|---|---|---|
| 数据库 | 直接查student表 | 有对应班级的学生数据 |
| 后端 | 访问 Servlet URL 带参数 | 返回的页面包含学生列表 |
| 前端 | 下拉框选班级点查询 | 列表只显示该班级学生 |
如果中间某一步不对,就停在那一步排查。数据库没有数据,后面都不用看。后端返回空,检查 SQL 和参数。前端没反应,看浏览器控制台有没有 JS 报错。
5.3 一个我踩过的坑:改完 Impl 忘了重新编译
有次改完StudentImpl.java,直接刷新页面,怎么都不生效。查了半天才发现 Tomcat 用的是WEB-INF/classes下的旧.class文件,源码改了但没重新编译。后来我养成习惯:改完 Java 文件,先确认 IDE 的自动编译开了,或者手动 Build 一次,再重启 Tomcat。从那以后每次改完 Impl 都强制走一遍「编译 → 部署 → 清浏览器缓存」的流程,省得再翻车。
希望这份拆解能帮你把这份 JSP 学生信息管理系统源码顺利跑起来,改出自己需要的样子。
本文还有配套的精品资源,点击获取