
简介这是一套基于JavaWeb的学生实习管理系统完整项目源码面向计算机相关专业正在做毕设的学生以及需要项目实战练习的Java学习者可直接作为毕业设计使用。系统采用B/S结构后台以JSP、Servlet、JDBC为核心框架MySQL作为数据库开发环境为JDK、Eclipse与Tomcat涵盖学生、老师、管理员三种角色学生可管理实习日志与实习反馈老师可对学生实习情况添加与查看评价管理员则负责班级、学生、老师、通知及实习信息的新增、查询与删除并可修改个人登录密码功能完善、界面美观、操作简单。资源包共3个文件包含项目源码压缩包、db_shixi.sql数据库脚本以及项目说明文档整体约4.88MB结构清晰导入即可运行。项目经过严格调试确保可正常启动已有3372人学习下载适合需要快速搭建实习实训管理系统、理解JavaWeb分层开发与数据库设计的读者参考借鉴。1. 从一份 JSPServlet 的实习管理系统源码说起很多同学做毕设时第一反应是上 SpringBootVue结果环境还没配好就卡在依赖冲突上。其实如果你的选题是「学生实习管理系统」这类偏信息管理的题目一套 JSPServletJDBC 的经典 JavaWeb 架构反而更稳——没有复杂的自动配置没有前后端分离的跨域问题Tomcat 一跑就能看到页面。这份资源就是这样一个项目源码、数据库脚本、项目说明打包在一起三种角色学生、老师、管理员的功能模块都写全了。它适合谁适合正在做毕设、需要一套能跑起来、能改、能写论文的 JavaWeb 项目的人也适合刚学完 Servlet 想找个完整案例练手的初学者。下面我从环境搭建讲到功能改造把这份源码拆开给你看。2. 环境搭建与项目导入JDK、Tomcat、Eclipse 三件套怎么配2.1 为什么这套技术栈对毕设反而友好先说说选型逻辑。JSPServletJDBC 是 JavaWeb 的「裸写」方式不依赖 Spring 容器不需要 Maven 拉一堆 jar 包。对于毕设场景这意味着三件事第一答辩时老师问「你的请求怎么处理的」你可以直接指着 Servlet 的doGet/doPost说清楚不用解释 SpringMVC 的 DispatcherServlet 怎么转发第二环境搭建简单装个 JDK、解压个 Tomcat、导入 Eclipse 就能跑不会出现「Maven 依赖下载失败」这种让人崩溃的问题第三代码结构直白src下按包分层WebContent下放 JSP数据库操作就是 JDBC 的Connection、PreparedStatement、ResultSet三板斧改起来没有心理负担。当然这套架构也有边界。它不适合高并发场景连接池需要自己配SQL 注入要靠PreparedStatement手动防。但毕设系统用户量就几十个这些都不是问题。我一般会建议如果你的题目是「XX 管理系统」且学校没强制要求 SpringBootJSPServlet 是性价比最高的选择。2.2 导入前的环境检查清单在导入项目之前先把这三样东西对齐版本否则后面报错会浪费大量时间。组件推荐版本检查方式常见问题JDK1.8java -version高版本 JDK 编译低版本项目可能报错Tomcat8.5 或 9.0启动后访问localhost:8080Tomcat 10 的 Servlet 包名变了老项目跑不了MySQL5.7 或 8.0mysql -u root -p8.0 需要改连接串的时区和驱动类Eclipse2019 及以上能创建 Dynamic Web Project需确认已装 JST Server Adapters这里重点说 Tomcat 版本。Tomcat 10 把javax.servlet改成了jakarta.servlet这份源码用的是javax包所以必须用 Tomcat 9 或更低版本。我见过有人装了 Tomcat 10 后所有 Servlet 报 404排查半天才发现是包名问题。JDK 同理1.8 最稳高版本编译时可能遇到Unsupported class file major version之类的错误。2.3 导入 Eclipse 并配置 Tomcat 的完整步骤假设你已经装好 JDK 1.8、Tomcat 9、MySQL 5.7接下来按步骤走。第一步解压项目包。你会看到shixi.zip源码压缩包和db_shixi.sql数据库脚本。先把shixi.zip解压到一个不含中文和空格的路径比如D:\workspace\shixi。第二步在 Eclipse 中导入项目。菜单File → Import → General → Existing Projects into Workspace选择解压后的shixi目录。如果 Eclipse 提示没有.project文件说明这个项目不是 Eclipse 工程格式需要手动创建 Dynamic Web Project 再把文件拷进去。第三步配置 Tomcat 运行时。右键项目 →Properties → Targeted Runtimes勾选你安装的 Tomcat 9。然后Properties → Java Build Path → Libraries确认 JRE 是 1.8并且有Apache Tomcat v9.0的库。第四步检查WebContent/WEB-INF/lib下是否有mysql-connector-java-x.x.x.jar。如果没有需要自己下载对应版本的驱动放进去并Add to Build Path。第五步启动 Tomcat。右键项目 →Run As → Run on Server选择 Tomcat 9启动后浏览器访问http://localhost:8080/shixi/。如果看到登录页说明部署成功。# 数据库导入命令在命令行执行 mysql -u root -p -e CREATE DATABASE shixi DEFAULT CHARACTER SET utf8mb4; mysql -u root -p shixi db_shixi.sql这段命令做了两件事先创建名为shixi的数据库并指定字符集为utf8mb4防止中文乱码然后把db_shixi.sql里的建表和初始数据导入进去。注意db_shixi.sql里可能已经包含CREATE DATABASE语句如果执行时报「database exists」可以先打开 sql 文件确认一下把重复的建库语句删掉再导入。2.4 数据库连接配置的修改位置导入数据库后还要改代码里的连接串。在src目录下找db或util包通常会有一个DBUtil.java或DBHelper.java。打开后找到类似下面的代码// 数据库连接配置根据自己环境修改 private static final String URL jdbc:mysql://localhost:3306/shixi?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai; private static final String USER root; private static final String PASSWORD 123456; private static final String DRIVER com.mysql.cj.jdbc.Driver;参数说明URL里的shixi是数据库名useUnicodetruecharacterEncodingutf8保证中文不乱码serverTimezoneAsia/Shanghai是 MySQL 8.0 必须加的时区参数不加会报The server time zone value is unrecognized。DRIVER如果是 MySQL 5.7用com.mysql.jdbc.Driver8.0 用com.mysql.cj.jdbc.Driver。改完保存重启 Tomcat 即可。3. 三种角色的功能模块拆解与代码走读3.1 学生角色实习日志与反馈的增查实现学生登录后主要用两个模块实习日志管理和实习反馈管理。这两个模块的逻辑几乎一样都是「添加 查看」属于典型的 CRUD 中的 Create 和 Read。先看实习日志的添加流程。前端 JSP 页面addLog.jsp里有一个表单提交到LogServlet。Servlet 的doPost方法接收参数调用 DAO 层插入数据库。// LogServlet.java 中处理添加日志的核心逻辑 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding(UTF-8); // 防止中文参数乱码 String title request.getParameter(title); String content request.getParameter(content); String date request.getParameter(date); int studentId (int) request.getSession().getAttribute(userId); // 从 session 取当前学生 ID Log log new Log(); log.setTitle(title); log.setContent(content); log.setDate(date); log.setStudentId(studentId); LogDao logDao new LogDao(); boolean success logDao.addLog(log); // 调用 DAO 插入 if (success) { response.sendRedirect(logList.jsp); // 添加成功跳回列表 } else { request.setAttribute(msg, 添加失败请重试); request.getRequestDispatcher(addLog.jsp).forward(request, response); } }逻辑说明request.setCharacterEncoding(UTF-8)必须放在获取参数之前否则中文会乱码。studentId从 session 里取而不是从表单传这样避免学生篡改 ID 查看别人数据。DAO 层用PreparedStatement执行INSERT返回布尔值表示是否成功。查看日志的 DAO 方法// LogDao.java 中查询某学生所有日志 public ListLog getLogsByStudentId(int studentId) { ListLog list new ArrayList(); String sql SELECT * FROM t_log WHERE student_id ? ORDER BY date DESC; try (Connection conn DBUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setInt(1, studentId); ResultSet rs ps.executeQuery(); while (rs.next()) { Log log new Log(); log.setId(rs.getInt(id)); log.setTitle(rs.getString(title)); log.setContent(rs.getString(content)); log.setDate(rs.getString(date)); list.add(log); } } catch (SQLException e) { e.printStackTrace(); } return list; }这里用try-with-resources自动关闭连接避免忘记close()导致连接泄漏。ORDER BY date DESC让最新的日志排在最前面。参数studentId通过ps.setInt(1, studentId)传入防止 SQL 注入。实习反馈模块的代码结构完全一致只是表名从t_log换成t_feedback字段略有不同。你可以照着日志模块自己改或者直接复用。3.2 老师角色实习评价的录入与关联查询老师登录后主要功能是给学生写实习评价。这个模块比学生端多了一个「关联查询」——老师需要先看到自己指导的学生列表再对某个学生写评价。评价添加的 Servlet 逻辑// EvaluateServlet.java 处理评价提交 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding(UTF-8); int studentId Integer.parseInt(request.getParameter(studentId)); int teacherId (int) request.getSession().getAttribute(userId); String content request.getParameter(content); String score request.getParameter(score); Evaluate eval new Evaluate(); eval.setStudentId(studentId); eval.setTeacherId(teacherId); eval.setContent(content); eval.setScore(score); EvaluateDao evalDao new EvaluateDao(); if (evalDao.addEvaluate(eval)) { response.sendRedirect(evalList.jsp); } else { request.setAttribute(msg, 评价提交失败); request.getRequestDispatcher(addEval.jsp).forward(request, response); } }关键点teacherId从 session 取studentId从表单取。为什么studentId可以从表单传因为老师选择的是自己指导的学生这个列表是后端根据teacherId查出来的学生无法伪造。但更严谨的做法是在插入前再校验一次「该学生是否属于该老师」防止有人手动改表单参数。查询评价列表时需要关联学生表获取学生姓名-- 查询某老师的所有评价关联学生表拿姓名 SELECT e.*, s.name AS student_name FROM t_evaluate e LEFT JOIN t_student s ON e.student_id s.id WHERE e.teacher_id ? ORDER BY e.id DESC;这条 SQL 用LEFT JOIN关联学生表这样即使学生信息被删除评价记录也不会丢失。AS student_name是给结果集列起别名方便在 JSP 里用${item.studentName}取值。3.3 管理员角色五个管理模块的通用套路管理员的功能最多班级管理、学生管理、老师管理、通知管理、实习信息管理。这五个模块的代码结构高度相似都是「列表 添加 删除 查询」。你只要搞懂一个剩下的就是复制粘贴改表名。以学生管理为例删除操作的 Servlet// StudentServlet.java 中删除学生的逻辑 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String action request.getParameter(action); if (delete.equals(action)) { int id Integer.parseInt(request.getParameter(id)); StudentDao studentDao new StudentDao(); boolean success studentDao.deleteStudent(id); response.sendRedirect(studentList.jsp?msg (success ? 删除成功 : 删除失败)); } }这里用action参数区分不同操作是 JavaWeb 里常见的「一个 Servlet 处理多个动作」的写法。删除成功后通过 URL 参数msg传递提示信息列表页读取后显示。查询功能通常带条件// StudentDao.java 中按姓名模糊查询 public ListStudent searchStudents(String keyword) { ListStudent list new ArrayList(); String sql SELECT * FROM t_student WHERE name LIKE ?; try (Connection conn DBUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setString(1, % keyword %); ResultSet rs ps.executeQuery(); while (rs.next()) { Student s new Student(); s.setId(rs.getInt(id)); s.setName(rs.getString(name)); s.setClassName(rs.getString(class_name)); list.add(s); } } catch (SQLException e) { e.printStackTrace(); } return list; }LIKE ?配合%keyword%实现模糊查询。注意setString里的%要拼在 Java 代码里不能写在 SQL 里写成LIKE %?%那样占位符不会被替换。通知管理和实习信息管理的代码几乎一样只是表名和字段不同。如果你要扩展功能比如加一个「实习成绩统计」可以在这个基础上加一个 Servlet 和 DAO 方法查询时用GROUP BY聚合。4. 避坑与排查导入运行中最容易翻车的五个点4.1 中文乱码从数据库到页面的全链路排查现象添加日志后列表页显示「测试」这样的乱码。原因乱码可能出现在三个环节——数据库字符集、JDBC 连接串、JSP 页面编码。任何一处不是 UTF-8 都会出问题。解决按顺序检查。第一数据库和表的字符集用SHOW CREATE TABLE t_log;确认是utf8mb4。第二JDBC 连接串加上useUnicodetruecharacterEncodingutf8。第三每个 JSP 页面顶部加% page contentTypetext/html;charsetUTF-8 languagejava %。第四Servlet 里request.setCharacterEncoding(UTF-8)必须在getParameter之前调用。四个地方都对了乱码才会消失。4.2 404 错误路径与 Tomcat 版本的常见陷阱现象启动 Tomcat 后访问http://localhost:8080/shixi/报 404。原因可能是项目没有部署到 Tomcat或者访问路径不对或者 Tomcat 版本不兼容。解决先在 Eclipse 的 Servers 视图里确认项目已添加。然后右键项目 →Properties → Web Project Settings看Context root是不是shixi。如果 Tomcat 是 10.x换成 9.x因为javax.servlet包在 Tomcat 10 里不存在了。还有一种情况是web.xml里配的url-pattern和实际访问路径不一致打开WEB-INF/web.xml核对一下。4.3 数据库连接失败驱动类与端口占用现象启动后访问登录页提交表单报java.sql.SQLException: No suitable driver found。原因MySQL 驱动 jar 没放到WEB-INF/lib下或者驱动类名写错了。解决确认WEB-INF/lib下有mysql-connector-java-5.1.x.jarMySQL 5.7或mysql-connector-java-8.0.x.jarMySQL 8.0。然后检查DBUtil.java里的DRIVER变量5.7 用com.mysql.jdbc.Driver8.0 用com.mysql.cj.jdbc.Driver。如果还报错看控制台有没有Communications link failure那说明 MySQL 服务没启动或端口不是 3306。4.4 修改密码后登录失效Session 与数据库不同步现象管理员修改密码后退出重新登录新密码登不上旧密码也不行。原因修改密码的 SQL 可能没执行成功或者更新时用了错误的用户 ID。解决打开ChangePasswordServlet检查UPDATE t_admin SET password ? WHERE id ?里的id是不是从 session 取的当前用户 ID。如果是从表单取的可能被篡改。另外确认executeUpdate()的返回值是不是大于 0如果等于 0 说明没更新到任何行。还有一种可能是密码做了 MD5 加密修改时忘了加密登录时却按加密后的比对。4.5 列表分页失效SQL LIMIT 与页码计算现象数据多了之后列表页只显示前几条翻页没反应。原因这份源码可能没做分页或者分页的LIMIT参数算错了。解决如果原项目没分页可以自己加。核心 SQL 是SELECT * FROM t_student LIMIT ?, ?第一个参数是偏移量(pageNum - 1) * pageSize第二个是每页条数。Servlet 里接收pageNum参数默认 1。JSP 页面底部加「上一页/下一页」链接传递pageNum。注意LIMIT的两个参数都必须是整数不能加引号。5. 从能跑到能答辩二次开发与论文素材提取技巧5.1 给系统加一个「实习统计」模块答辩时老师常问「你的系统有什么亮点」。如果只是增删改查确实单薄。我一般会建议加一个统计模块用GROUP BY做聚合查询代码量不大但效果明显。// StatDao.java 统计每个班级的实习人数 public ListMapString, Object countByClass() { ListMapString, Object list new ArrayList(); String sql SELECT c.name AS class_name, COUNT(s.id) AS student_count FROM t_class c LEFT JOIN t_student s ON c.id s.class_id GROUP BY c.id, c.name; try (Connection conn DBUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { ResultSet rs ps.executeQuery(); while (rs.next()) { MapString, Object map new HashMap(); map.put(className, rs.getString(class_name)); map.put(studentCount, rs.getInt(student_count)); list.add(map); } } catch (SQLException e) { e.printStackTrace(); } return list; }这段代码用LEFT JOIN保证没有学生的班级也显示COUNT(s.id)统计学生数。返回ListMap而不是实体类是因为统计结果的字段不固定用 Map 更灵活。JSP 页面用c:forEach遍历显示成表格就是一个「班级实习人数统计」功能。5.2 论文里怎么描述这套系统的技术架构写论文时不要只贴代码。我一般会按这个结构写先画一个 B/S 架构图用 Visio 或 draw.io说明浏览器、Tomcat、MySQL 三层的关系。然后写「系统采用 JSPServletJDBC 的经典 JavaWeb 架构JSP 负责视图展示Servlet 负责请求分发和业务逻辑JDBC 负责数据持久化」。接着写「数据库设计遵循第三范式共 X 张表包括学生表、老师表、班级表、日志表、评价表等」把表结构用表格列出来。最后写「系统实现了三种角色的权限隔离通过 Session 存储登录状态不同角色登录后跳转到不同的功能主页」。这样写既体现了技术选型又展示了工作量比单纯说「我用了 JavaWeb」有说服力得多。5.3 答辩前必须走一遍的自检清单从那以后我每次帮人看毕设项目都强制走一遍这个流程第一步删掉 Tomcat 里的部署重新Run on Server确认从零启动能跑通。第二步用三个角色分别登录每个功能点一遍特别是添加和删除。第三步把数据库导出成 SQL 文件删库重建再导入一次确认脚本完整。第四步改一个 JSP 页面的标题重新部署确认修改生效。第五步打开浏览器控制台看有没有 JS 报错或 404 的资源请求。这五步走完基本不会在答辩现场翻车。希望帮到你。本文还有配套的精品资源点击获取