资讯动态

JSP+Servlet+MySQL教务管理系统毕业设计:部署、源码解析与避坑指南

发布时间:2026/10/9 3:58:10 来源:尧图企业网站定制
简介面向高校计算机相关专业毕业设计及Java Web初学者的教务管理系统完整项目。系统基于JSPServletMySQL实现覆盖学生信息管理、课程分配、成绩记录等核心教务场景包含可运行的完整源码及数据库初始化脚本可直接部署学习或二次开发。包体共535个文件以gif与jpg界面截图、jsp页面、java及class源码文件为主另有jar依赖库、sql建表脚本和配置文件压缩包约9.87MB目录结构清晰。已有1132人学习下载。借助项目可同时理解前端页面交互、Servlet后端请求处理与MySQL数据操作掌握经典三层Web开发模式。1. 教务管理系统jspservletmysql毕业设计老技术栈为什么还是答辩主力拿到“105毕业设计”这样一个 rar 压缩包里面是一个 jspservletmysql 的教务管理系统第一反应往往是“这年头谁还写 JSP”可真到部署和答辩时你会发现这条老链路依然承包着大量本科毕业设计。原因很简单JSP 负责页面Servlet 负责请求和控制MySQL 负责数据三层拆得足够直白相比 springboot 全家桶它能现场讲清一条请求从浏览器走到数据库的完整路径评委问不出死角。这篇笔记就是照着这套源码包的常见形态把环境、数据库、核心代码和典型坑一次讲完。2. 把 rar 里的教务系统跑起来JDK/Tomcat/MySQL 版本搭配和导入启动顺序2.1 版本搭配JDK8、Tomcat8.5、MySQL5.7 还是 8.0先给一个我踩过很多次坑之后固定的三件套JDK 1.8、Tomcat 8.5、MySQL 5.7.44 或 8.0.x。不要看到新版本就手痒尤其不要直接上 JDK17 配 Tomcat10。Tomcat 10 把包名从 javax.servlet 换成了 jakarta.servlet老项目里的 import javax.servlet.http.HttpServlet 全部编译不过源码包再完整也白搭。JDK8 配 Tomcat8.5 是这套 jspservlet 源码兼容性最稳妥的组合绝大多数 2015 到 2020 年之间的 JavaWeb 毕业设计在这套环境下都能一次编译通过。MySQL 选 5.7 还是 8.0要看连接驱动 jar 怎么配合。老项目里常放的是 mysql-connector-java-5.1.x这个驱动直连 MySQL 8.0 大概率报 “Public Key Retrieval is not allowed”反过来 8.0 时代的 com.mysql.cj.jdbc.Driver 也可以连 5.7但要额外带 serverTimezone 参数。我的建议是如果源码包里 db.properties 或 JDBC 工具类里写的是 com.mysql.jdbc.Driver优先给这台机器装 MySQL 5.7.44如果你只想统一装 8.0那必须把驱动 jar 换成 8.x 并且改驱动类名。两种方式都能跑别让驱动和数据库版本互相别扭就行。这套组合的教务管理系统本质是一个标准 JavaWeb 完整案例链路是浏览器请求到 TomcatTomcat 把请求分给 ServletServlet 调 DAODAO 用 JDBC 访问 MySQL。理解这条链路比记版本号有用你后面改任何配置都是为了让这条链路上的每个接头都能对上。2.2 解压导入 Eclipse/IDEA从 rar 压缩包到浏览器可访问收到压缩包先别急着双击运行先解压并确认目录结构。常见做法是项目根目录下有 src、WebContent或 WebRoot、build/classes、以及一个放数据库脚本的 db 文件夹有些打包者会把 SQL 脚本放在根目录也可能打包进一个 word 文档里。找一个 readme.txt 或“运行说明.doc”读一遍把里面的数据库密码和端口抄下来这一步能省掉后面大量瞎猜时间。我一般会先在 src 里全局搜一遍 jdbc把数据库连接串、用户名、密码三个变量找出来确认它连的是哪个库。同时看一眼 web.xml 里的欢迎页和 servlet 映射确认登录页是 login.jsp 还是 index.jsp这决定了你启动后第一个访问的 URL 是什么。不要直接在 Tomcat 里塞 war 包很多毕设源码没有打成 war 的配置直接扔 war 反而容易缺资源。如果是 IDEA用 File - Open 选中项目根目录选择信任并继续IDEA 识别为普通目录时右键项目根目录 Add Framework Support 勾选 Web再把 src 目录标记为源代码目录把 WebContent 标记为 Web 资源目录。如果是 Eclipse用 Import - Existing Projects into Workspace 选择根目录就行老项目的 .classpath 和 .project 文件通常还在导入后基本不用额外配。操作完成后检查 Project Structure 里的 Artifacts确认输出目录里有 WEB-INF/classes 和 lib这是很多新手导入后页面 404 的根源。2.3 初始化数据库SQL 脚本、连接配置和首次连库验证数据库要先行。先启动 MySQL 服务Windows 上可以在服务管理器里找到 MySQL57 或 MySQL80 启动然后建库、导入脚本CREATE DATABASE IF NOT EXISTS edu_system DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE edu_system; SOURCE D:/work/edu_system.sql;脚本执行完先别关命令行直接敲几条常用命令验证表是不是真的建出来了SHOW TABLES; SELECT COUNT(*) FROM student; DESC admin;注意 SOURCE 后面不要用反斜杠路径MySQL 命令行会把它当成转义符处理建议统一用正斜杠。如果你用的是可视化工具图形界面里选中 edu_system 库再“运行 SQL 文件”目标库必须先选中否则表会跑到别的库下面去这是后面“找不到表”的头号原因。脚本导完后回到刚才全局搜到的连接配置位置把 URL、账号、密码改成你本机的值。这里最容易错的是连接串里的库名和端口MySQL 默认 3306如果你安装时改成 3307程序里还是 3306启动后报错就是“Cannot create PoolableConnectionFactory”。改完配置启动 Tomcat控制台没有异常浏览器访问 http://localhost:8080/项目名/ 能打开登录页说明环境这一关过了。3. 拆开黑匣子jspservletmysql 如何完成一次登录、查询和权限控制3.1 从 JSP 表单到 Servlet一个最简单的 servlet demo 怎么写很多人把 Servlet 想得很玄其实它就是 Java 写的一个类专门接 HTTP 请求。浏览器提交一个表单Tomcat 根据 web.xml 或注解里的地址映射把请求交给对应 Servlet 的 doGet 或 doPost 方法。下面这个是最经典的 servlet demo——登录WebServlet(/login) public class LoginServlet extends HttpServlet { Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding(UTF-8); String username request.getParameter(username); String password request.getParameter(password); UserDao dao new UserDao(); User user dao.findByUsernameAndPassword(username, password); if (user ! null) { request.getSession().setAttribute(loginUser, user); response.sendRedirect(request.getContextPath() /index.jsp); } else { request.setAttribute(msg, 用户名或密码错误); request.getRequestDispatcher(login.jsp).forward(request, response); } } }两个关键点要解释清楚。第一行 setCharacterEncoding 必须写在读取参数之前而且只在 POST 请求下有意义GET 请求的参数编码由 Tomcat 的 URIEncoding 决定这就是为什么有时改了页面编码还乱码。request.getParameter 拿到的是表单里 name 属性同名控件的值login.jsp 里 input 的 name 必须和这里完全一致差一个字母就永远登录不进去。校验成功后用 response.sendRedirect 重定向浏览器 URL 会变成 index.jsp退出登录再按浏览器后退键也不会重新提交表单这是“重定向 vs 转发”在答辩时最好讲的一段。实际源码包里往往不会只写一个 LoginServlet管理员、学生、老师登录分别对应不同入口或者共用一个 Servlet 加 role 参数判断。构造一个项目时我会把“登录”单独拆出来让乘客只用登录逻辑不要在里面塞菜单权限判断否则后面改一个角色权限就要动登录代码。3.2 用 Filter 做登录拦截session 判断和权限边界的写法教务系统里最典型的需求是没登录的人不能直接输入 URL 跳进管理页面。这里靠的就是 Filter。Servlet 规范里 Filter 会先于 Servlet 执行并拦截请求最常见的实现是用 session 里的用户对象做判断WebFilter(/admin/*) public class AdminAuthFilter implements Filter { Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request (HttpServletRequest) req; HttpServletResponse response (HttpServletResponse) res; Object admin request.getSession().getAttribute(adminSession); if (admin null) { response.sendRedirect(request.getContextPath() /login.jsp); return; } chain.doFilter(req, res); } }这里有一个很隐蔽的坑如果你的页面结构是 jsp/admin/index.jspjsp 文件直接放在 admin 目录下那 Filter 的拦截路径要写 /admin/*并且登录成功后要重定向到 /admin/index.jsp而不是 index.jsp否则每次跳转都会被 Filter 拦回去形成死循环。很多拿到源码包的人遇到的“登录进不去”并不是密码错而是登录成功后的跳转地址被自己写的 Filter 拦住了。权限边界要结合 session 设计学生、老师、管理员是三个角色不要给所有人同一个 loginUser 属性。我一般会分别存 session.setAttribute(studentSession, stu) 和 session.setAttribute(adminSession, admin)Filter 按目录分别拦截这样两个角色即使共用一套 JSP也不会出现学生访问管理员菜单的越权问题。答辩时主动讲这段通常能直接避过“你系统安全吗”这一问。3.3 JDBC 查询与 JSP 渲染把学生列表渲染成页面的最小闭环业务数据最终要落到 MySQLServlet 里的 UserDao 只是一个壳真正干活的是 JDBC。以查学生列表为例DAO 层方法通常长这样public ListStudent findByKeyword(String keyword) { ListStudent list new ArrayList(); String sql SELECT id, stu_no, name, class_name FROM student WHERE name LIKE ?; try (Connection conn DBUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setString(1, % keyword %); try (ResultSet rs ps.executeQuery()) { while (rs.next()) { Student s new Student(); s.setId(rs.getInt(id)); s.setStuNo(rs.getString(stu_no)); s.setName(rs.getString(name)); s.setClassName(rs.getString(class_name)); list.add(s); } } } catch (SQLException e) { e.printStackTrace(); } return list; }PreparedStatement 有两个比 Statement 先进的地方一是不用拼字符串占位符 ? 按位置填参数传进来的关键词无论带多少引号都只会被当成普通字符串这是最简单有效的 SQL 注入防线二是数据库会对同一条 SQL 做预编译缓存循环查一万条数据时性能差别很明显。JDBC 连接不直接写死在这个方法里是对的DBUtil.getConnection() 从连接池拿连接用完自动归还避免了手动 close 的繁琐和漏关连接。Servlet 拿到这个 List 之后把它塞进 request 属性转发到 jsp 页面。JSP 里用 JSTL 的 c:forEach 比用 scriptlet 好维护得多但很多老毕设代码还在用 scriptlet能跑答辩时如果被问到为什么不分开你可以补一句“用 JSTL 重构后的版本更清晰”。学生个人信息展示页面、选课列表、成绩列表都是同一种套路查一张表或两张表 joinList 到页面循环渲染成表格。确认你能独立写通这条链路后面加什么功能都是复制粘贴微调。4. MySQL 建模与配置教务系统表结构、外键取舍和连接池参数4.1 教务系统六张核心表的字段设计看源码包里的 .sql 文件你会发现几乎每个教务系统都绕不开这几张表学生、教师、课程、成绩、选课、管理员。区别只是在字段命名和是否拆表。以最小可用模型来设计表结构大概是这样表名核心字段说明studentid, stu_no, name, password, class_name, major, phone学生信息teacherid, tea_no, name, password, title教师信息courseid, course_no, name, credit, teacher_id课程归属教师scoreid, student_id, course_id, score成绩记录enrollid, student_id, course_id, enroll_time选课记录adminid, username, password管理员账号字段类型上id 用 INT 自增主键学号、工号这类编号用 VARCHAR 而不是 INT因为里面可能会有前导零或字母score 分数用 DECIMAL(5,1) 或 INT 都可以如果要求精确到 0.5DECIMAL 更合适。密码列不要用明文哪怕零基础也至少存个 MD5毕业设计中用 DigestUtils.md5Hex(password) 一行就能搞定。这个点写进论文的设计部分比堆十张表更能拿分。表和表之间的关系也很直白teacher 和 course 是一对多用 teacher_id 挂接enroll 和 score 都引用 student_id 和 course_id。你会在 SQL 脚本里看到大量命名字段比如 sbirthday、saddress 这类缩写老项目常见但建议新写代码时用全称减少跟数据库字段对不上的低级错误。4.2 外键和唯一索引什么时候加、什么时候别加这是毕设里最容易暴露水平的点。很多教材把外键当成标准答案但真实项目中物理外键用得越来越克制原因在于删除和更新时要层层校验报错信息对用户完全不友好。常见做法是保留外键关系但不一定建 FOREIGN KEY 约束而是在应用层保证引用完整性也就是逻辑外键。答辩论据很简单选课表里 student_id 是不是真的存在由程序校验数据库只负责存数据这样删除学生时不会因为成绩表里还有记录而拒绝删除。那物理外键什么时候值得加呢像成绩表这种强一致要求、且基本不会删除历史数据的表可以加 ON DELETE CASCADE至于 student 和 enroll 之间建议慎重因为选课记录删掉是会出学术问题的。索引这一块我给两个最实用的学号要建唯一索引防止同一学号插两遍选课表在 student_id、course_id 上建联合唯一索引保证同一学生不能重复选同一门课ALTER TABLE student ADD UNIQUE INDEX uk_stu_no (stu_no); ALTER TABLE enroll ADD UNIQUE INDEX uk_enroll (student_id, course_id);这两条 SQL 执行完从数据层面把最典型的脏数据堵死了。注意唯一索引一旦建立程序里插入重复记录会抛 DuplicateKeyException需要配套捕获这个异常并回滚业务提示否则用户看到的是 500 报错页面。4.3 连接池和中文乱码dbcp 参数与 JDBC URL 编码老项目里数据库连接不会每次 new 一个 Connection那样太慢常见做法是用连接池。编码上最能见真章的一个地方是 jdbc.propertiesjdbc.drivercom.mysql.jdbc.Driver jdbc.urljdbc:mysql://localhost:3306/edu_system?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai jdbc.usernameroot jdbc.password123456 jdbc.maxActive20 jdbc.maxIdle5 jdbc.initialSize3逐项说driver 如果是 MySQL5.7用 com.mysql.jdbc.Driver如果用的是 MySQL8.0 的驱动这一行必须换成 com.mysql.cj.jdbc.Driver。URL 里的 useUnicodetruecharacterEncodingutf8 缺一不可不加 characterEncoding中文写进 MySQL 后再读出来就是问号serverTimezone 是 MySQL8 驱动强制的参数5.7 驱动不认也不报错但 8.x 驱动不加就抛异常。最大连接数 maxActive 不要拍脑袋写 200一个毕设系统实际并发通常个位数20 足够写太大反而浪费内存。中文乱码还有一层容易漏MySQL 库表和字段的字符集必须和连接串一致。SQL 脚本建表时如果有 DEFAULT CHARSETutf8 而库是 utf8mb4写 emoji 或生僻字就会失败。统一的建议是创建库时就用 utf8mb4连接串里也写 utf8mb4一了百了。5. 避坑排查jspservletmysql 毕业设计跑不起来的 5 个翻车现场5.1 Tomcat 启动失败端口占用和 jar 包缺失的排查顺序现象Eclipse 或 IDEA 里点启动控制台红字报 Port 8080 required by Tomcat v8.5 Server is already in use或者启动到一半就崩了。原因大概率有两个方向要么 8080 被占用要么项目引用的 jar 没有打进发布目录。先解决端口命令行输入 netstat -ano | findstr 8080看到占用 PID 后在任务管理器里确认是不是另一个 Tomcat 或 Java 进程确认后强杀或换端口。这个动作流程是可以直接帮你摆脱“端口冲突”这个最常见的启动失败场景。jar 包缺失的表现更隐蔽Tomcat 起来了一访问某个页面就报 ClassNotFoundException比如 com.mysql.jdbc.Driver。这时候去项目的 WEB-INF/lib 目录看一眼mysql-connector-java 的 jar 在不在。很多源码包为了减小体积把 jar 单独放在根目录 lib 文件夹里需要手动复制到部署目录。IDEA 里要确认 Artifacts 的输出包含 libEclipse 里确认 Deployed Assembly 里有没有把 lib 勾进 WEB-INF。处理完这两板斧80% 的启动问题能解决。5.2 MySQL 连接失败驱动包、时区和密码加密规则现象项目能启动登录页能打开一点登录就报 Cannot create PoolableConnectionFactory 或者 Communications link failure。原因排序驱动类名写的和 jar 对不上、连接串缺失 serverTimezone、MySQL8 默认的 caching_sha2_password 认证方式老驱动不支持。解决时先做左右隔离用一个最小的 JDBC 测试类直接 new URL、User、Password 试连报错信息比 Tomcat 里包一层后的更直接。测试通过再去改项目配置。MySQL 5.7.44 的安装过程如果在 Windows 上踩了坑多半是服务启动失败和初始密码找不到。初始密码去安装目录下的 data 目录里的 .err 文件里面找temporary password 那行就是。另外用 mysql -u root -p 之后密码输错几次MySQL 会锁连接需要执行 FLUSH PRIVILEGES 才能解开。这套排查顺序是我处理 JavaWeb 项目连带 MySQL 问题时固定用的流程少走很多弯路。5.3 JSP 页面乱码页面、请求、数据库三段编码现象页面上中文全是问号或者锟斤拷。原因是一个链路三个环节编码不一致。第一段是 JSP 页面本身的编码文件头要有 % page contentTypetext/html;charsetUTF-8 %IDE 右下角确认文件编码也是 UTF-8第二段是请求编码POST 请求要在 Servlet 里 request.setCharacterEncoding(UTF-8)GET 请求要在 Tomcat 的 server.xml 里给 Connector 加 URIEncodingUTF-8第三段是 MySQL连接串加 characterEncodingutf8表和库都用 utf8mb4。三段都对齐乱码基本绝迹。还有一个容易被忽视的点JSP 文件里的中文字符在编辑时被存成了 GBK即使页面声明 UTF-8 也会乱码。这种情况无解只能把文件在 IDEA 里把 Global Encoding 和 Project Encoding 都设为 UTF-8 后重新保存。验证乱码是否修好不要只盯着页面直接在 mysql 命令行里 SELECT 一遍看库里存的对不对能分清是写进去就错了还是读出来才错的。5.4 数据库找不到表SQL 脚本落到了错误的库上现象Tomcat 正常登录成功一进学生管理页就报 Table edu_system doesnt exist 或 unknown column。原因九成是 SQL 脚本被执行到了默认库或另一个同名库下面。尤其用可视化工具导入时很多人连接的是 root 用户左侧树里默认选中 mysql 系统库运行 SQL 文件后表全部建到了 mysql 库里程序连的却是 edu_system。解决方式导入前先用 CREATE DATABASE 把目标库建好工具里右键目标库 - 运行 SQL 文件而不是双击连接点运行导入后第一时间执行 SHOW TABLES; 确认表确实存在。如果程序里连的表名和脚本里建的表名不一致说明源码包里的 SQL 脚本版本和 DAO 层不匹配这属于源码本身的问题处理办法是去 DAO 里抄出所有表名和字段名再和脚本逐一对一遍差哪个补哪个。表多的时候确实累但这是能跑起来的地基。5.5 功能一跑就出错Filter 拦截登录请求或 Servlet 映射冲突现象登录按钮点下去URL 跳到了 login.jsp或者报 404/405。原因里最多的是 Filter 把登录请求也拦截了。如果你写了 WebFilter(/) 拦截所有路径又在 doFilter 里要求必须有 session 用户那么 LoginServlet 压根进不去所有请求都被送回登录页形成死循环。解决拦截路径收窄到 /admin/、/student/* 这类受保护目录并放行 login.jsp、LoginServlet 以及静态资源 css、js、图片。405 通常是 doGet 和 doPost 不匹配表单 methodpost 而 Servlet 只重写了 doGetTomcat 找不到处理 POST 的方法就报 405。Servlet 映射冲突则是在 web.xml 和注解里同时配了同一个 URL容器启动时会有明确警告顺手把 web.xml 里的旧映射删掉即可。排查这类问题有个固定节奏先看 URL 地址对不对再看 Filter 拦没拦再看方法手势一套流程下来基本能定位。6. 从“能跑”到“能答辩”给教务系统加一个可演示的密码重置功能一个只会列表和登录的教务系统答辩时容易被问“你这个系统有什么实际价值”。与其解释不如现场演示一个高频管理动作管理员一键重置学生密码。这个功能规模小一个 JSP 按钮、一个 Servlet 方法、一条 UPDATE正好把 JSPServletMySQL 三条链路再串一遍评委一眼就能看懂。String sql UPDATE student SET password ? WHERE id ?; try (Connection conn DBUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setString(1, DigestUtils.md5Hex(123456)); ps.setInt(2, Integer.parseInt(request.getParameter(sid))); int rows ps.executeUpdate(); if (rows 0) { response.sendRedirect(student_list.jsp?msgreset_ok); } else { request.setAttribute(msg, 学生不存在); request.getRequestDispatcher(student_list.jsp).forward(request, response); } }这里最关键的两个细节密码重置前先用 MD5 转一次保证库里存的永远是摘要而不是明文执行 UPDATE 后判断 rows 是否大于 0大于 0 才跳转等于 0 说明这个学生 id 不存在不能静默吞掉。演示时配一句“为什么存摘要”比背十页论文都有效。我给自己做内部控制台时第一版也用明文存密码后来连自己都看不下去才补的摘要血泪经验是安全该从第一行代码开始养成习惯而不是答辩前临时补课。希望这篇落地笔记能让你少踩几个我当年踩的坑顺利把那份源码跑起来、讲明白。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑