Java学生宿舍管理系统毕设实战:JSP+MySQL从环境搭建到答辩避坑 简介这份资源是面向高校计算机相关专业学生与Java Web初学者的一份学生宿舍管理系统毕业设计文档以塔里木大学宿舍管理为背景针对传统人工、单机管理方式效率低、数据易错易丢失等问题给出了一套基于B/S模式的Web化解决方案。系统采用JSPMySQL技术栈划分系统管理员、宿舍管理员和学生三类角色涵盖用户登录、学生注册、学生与管理员管理、宿舍管理、组合查询及宿舍管理员管理等核心功能。文档围绕J2EE、MySQL、JSP、B/S架构、TOMCAT等关键技术展开并完整呈现系统需求分析、业务流程分析、功能模块设计、数据库概念与逻辑结构设计、系统实现及功能测试等章节目录结构清晰便于读者理解一个完整Java Web项目的开发脉络。资源包为1个docx文件约1.44MB已有204人学习适合作为课程设计或毕业设计的参考模板帮助读者快速掌握从需求到实现的整体思路与文档撰写方法。1. 从一份 JSP 毕设文档说起这套 Java 宿舍管理系统到底能跑通什么如果你手头正压着一份“基于 Java 学生宿舍管理系统设计与实现”的文档或者导师刚把题目甩过来让你两周内交东西那这套 JSPMySQL 的 B/S 方案大概率是你绕不开的选项。它不是什么高深架构没有 Spring Boot 全家桶也没有 Vue 前后端分离就是最朴素的 JSP 直连数据库、Servlet 接请求、Tomcat 跑服务。但恰恰是这种“老派”组合在毕设场景里反而最稳——环境好配、代码好懂、答辩时老师问不倒你。这套系统覆盖了系统管理员、宿舍管理员、学生三个角色核心功能包括登录注册、学生信息管理、宿舍楼管理、考勤记录、报修审核、来访登记基本把高校宿舍管理的日常流程都串起来了。适合谁适合需要快速交付一个能演示、能讲清业务逻辑的 Java Web 毕设的同学也适合刚接触 JSP 想拿一个完整项目练手的初学者。下面我按“先跑起来、再改得动、最后避坑”的顺序把这份资源拆开讲。2. 环境搭建与数据库落地从 JDK 到五张表的完整初始化2.1 为什么这套技术栈选 JSP 而不是 Spring Boot先把这个事说清楚免得你中途动摇。这套系统用的是 JSPServletMySQLTomcat不是现在招聘市场上满天飞的 Spring Boot MyBatis-Plus。原因很直接毕设场景下JSP 的请求响应模型是透明的你在浏览器点一个按钮请求进到哪个 Servlet、调了哪条 SQL、返回哪个 JSP 页面整条链路在 Eclipse 里一眼能跟到底。Spring Boot 虽然开发快但自动配置把很多细节藏起来了答辩时老师问“你这个登录请求怎么走到数据库的”你要是只会说“框架自动处理的”场面会很难看。另外这套系统的数据库表结构非常清晰五张表——t_admin、t_student、t_dromAdmin、t_dromBuild、t_visitor——字段和关系都在文档里列得明明白白你照着建表就能跑不需要额外理解 ORM 映射。常见做法是先用 Navicat 把库和表建好再回头调 Java 代码这样出错时能快速定位是数据库问题还是代码问题。2.2 开发环境版本对齐与 Tomcat 配置文档里写的开发环境是 Windows 7 Eclipse 4.5 MySQL 5.5.62 JDK 1.7/1.8 Tomcat 7/8。你现在的机器大概率是 Win10/Win11这没关系但版本别乱跳。我一般会这样配# 检查 JDK 版本确保是 1.8JSP 项目用 1.8 最稳高版本会有模块化报错 java -version # 输出应为 java version 1.8.0_xxx # 检查 MySQL 服务是否启动 net start mysql # 如果服务名不是 mysql用 sc query 查一下实际服务名 # 检查 Tomcat 端口是否被占用默认 8080 netstat -ano | findstr :8080JDK 选 1.8 是因为 Tomcat 7/8 对高版本 JDK 的兼容性会出玄学问题比如 JSP 编译时提示“无法解析 javax.servlet”之类的。MySQL 用 5.7 也行但注意 5.7 默认字符集是 latin1建库时要手动指定 utf8mb4否则学生姓名里的生僻字会变问号。Tomcat 解压后别急着放中文路径放在D:\tomcat8这种纯英文目录下Eclipse 里配置 Server Runtime 时指向这个目录即可。配置完成后在 Eclipse 里新建 Dynamic Web Project把WebContent目录下的 JSP 文件和src下的 Java 包结构对照文档目录树放好右键项目 Run As → Run on Server能在浏览器看到登录页就算环境通了。2.3 五张核心表的建表 SQL 与字段说明文档里给了表结构但没给完整建表语句。我按它的字段定义补一份可直接执行的 SQL你拿去在 Navicat 里跑一遍就行-- 创建数据库字符集必须指定 utf8mb4 CREATE DATABASE dorm_system DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE dorm_system; -- 系统管理员表 CREATE TABLE t_admin ( t_adminId INT(10) NOT NULL AUTO_INCREMENT COMMENT 管理员编号, t_userName VARCHAR(20) NOT NULL COMMENT 管理员姓名, t_password VARCHAR(20) NOT NULL COMMENT 密码, t_name VARCHAR(20) DEFAULT NULL COMMENT 姓名, t_sex VARCHAR(2) DEFAULT NULL COMMENT 性别, t_tel VARCHAR(11) DEFAULT NULL COMMENT 电话, PRIMARY KEY (t_adminId) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT系统管理员表; -- 学生信息表 CREATE TABLE t_student ( t_studentId INT(20) NOT NULL AUTO_INCREMENT COMMENT 学生编号, t_stuNum VARCHAR(20) NOT NULL COMMENT 学生学号, t_password VARCHAR(20) NOT NULL COMMENT 账号密码, t_name VARCHAR(20) DEFAULT NULL COMMENT 学生姓名, t_dormBuildId INT(20) DEFAULT NULL COMMENT 宿舍楼编号, t_dormName VARCHAR(20) DEFAULT NULL COMMENT 宿舍楼名称, t_sex VARCHAR(2) DEFAULT NULL COMMENT 性别, t_tel VARCHAR(11) DEFAULT NULL COMMENT 电话, t_stuClass VARCHAR(20) DEFAULT NULL COMMENT 学生班级, t_stuacademy VARCHAR(20) DEFAULT NULL COMMENT 学生院系, PRIMARY KEY (t_studentId) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT学生信息表; -- 宿舍管理员信息表 CREATE TABLE t_dromAdmin ( t_dormManId INT(10) NOT NULL AUTO_INCREMENT COMMENT 宿舍管理员编号, t_userName VARCHAR(20) NOT NULL COMMENT 宿舍管理员姓名, t_password VARCHAR(20) NOT NULL COMMENT 账号密码, t_dormBuildId INT(20) DEFAULT NULL COMMENT 宿舍楼编号, t_name VARCHAR(20) DEFAULT NULL COMMENT 姓名, t_sex VARCHAR(2) DEFAULT NULL COMMENT 性别, t_tel VARCHAR(11) DEFAULT NULL COMMENT 电话, PRIMARY KEY (t_dormManId) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT宿舍管理员信息表; -- 宿舍楼信息表 CREATE TABLE t_dromBuild ( t_dormId INT(10) NOT NULL AUTO_INCREMENT COMMENT 宿舍编号, t_dormBuildId INT(20) DEFAULT NULL COMMENT 宿舍楼编号, t_dormName VARCHAR(20) DEFAULT NULL COMMENT 宿舍楼名称, t_dormType VARCHAR(10) DEFAULT NULL COMMENT 宿舍楼属性, t_dormNumber INT(10) DEFAULT NULL COMMENT 宿舍楼房间号, PRIMARY KEY (t_dormId) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT宿舍楼信息表; -- 来访者信息表 CREATE TABLE t_visitor ( t_visitorId INT(18) NOT NULL COMMENT 来访者身份证号码, t_visitorRecord INT(20) DEFAULT NULL COMMENT 来访记录, t_visitorName VARCHAR(20) DEFAULT NULL COMMENT 来访者姓名, t_sex VARCHAR(2) DEFAULT NULL COMMENT 来访者性别, t_time DATETIME DEFAULT NULL COMMENT 来访日期, t_tel VARCHAR(11) DEFAULT NULL COMMENT 来访者电话, PRIMARY KEY (t_visitorId) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT来访者信息表;建表时注意几个点t_visitorId用的是 INT(18)但身份证号实际是 18 位字符串这里文档定义成 INT 其实存不下完整身份证号你实际用的时候建议改成 VARCHAR(18)否则插入会溢出。t_dromBuild和t_dromAdmin的拼写是文档原文的写法drom 不是 dorm你代码里的实体类名和 SQL 语句必须跟这个保持一致不然查不到数据。另外t_student表里同时存了t_dormBuildId和t_dormName这是冗余设计但毕设场景下反而方便——查学生信息时不用连表就能显示宿舍楼名称。3. 登录鉴权与角色分流Servlet 里怎么把三种用户区分开3.1 登录请求的完整链路与 Session 存储这套系统的登录逻辑不复杂但它是整个系统的入口搞懂了这里后面所有模块都是同一个套路。流程是这样的用户在login.jsp输入账号密码表单以 POST 方式提交到某个 Servlet文档里没写具体类名常见做法是叫LoginServletServlet 从request.getParameter()拿到用户名和密码然后去数据库对应的表里查。系统管理员查t_admin宿舍管理员查t_dromAdmin学生查t_student。查到了就把用户信息塞进HttpSession然后根据角色跳转到不同的主页 JSP。// LoginServlet.java 核心逻辑 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding(UTF-8); String userName request.getParameter(userName); String password request.getParameter(password); String role request.getParameter(role); // 登录页下拉框选择角色 Connection conn null; PreparedStatement ps null; ResultSet rs null; try { conn DBUtil.getConnection(); // 自己封装的数据库连接工具类 String sql ; if (admin.equals(role)) { sql SELECT * FROM t_admin WHERE t_userName? AND t_password?; } else if (dormAdmin.equals(role)) { sql SELECT * FROM t_dromAdmin WHERE t_userName? AND t_password?; } else { sql SELECT * FROM t_student WHERE t_stuNum? AND t_password?; } ps conn.prepareStatement(sql); ps.setString(1, userName); ps.setString(2, password); rs ps.executeQuery(); if (rs.next()) { HttpSession session request.getSession(); session.setAttribute(userName, userName); session.setAttribute(role, role); // 根据角色跳转不同页面 if (admin.equals(role)) { response.sendRedirect(admin/index.jsp); } else if (dormAdmin.equals(role)) { response.sendRedirect(dormAdmin/index.jsp); } else { response.sendRedirect(student/index.jsp); } } else { request.setAttribute(msg, 账号或密码错误); request.getRequestDispatcher(login.jsp).forward(request, response); } } catch (SQLException e) { e.printStackTrace(); } finally { DBUtil.close(conn, ps, rs); } }这段代码的关键在于role参数——登录页必须有一个下拉框让用户选身份否则光凭账号密码没法判断去查哪张表。Session 里存了userName和role后面每个需要登录才能访问的页面都在顶部用 JSP 脚本片段检查 Session比如% if(session.getAttribute(userName)null){ response.sendRedirect(login.jsp); } %。这种写法虽然土但毕设够用而且逻辑一目了然。3.2 三种角色的权限边界与页面跳转系统管理员登录后进admin/index.jsp能操作学生管理、宿舍管理员管理、宿舍楼管理、来访记录查看。宿舍管理员进dormAdmin/index.jsp能处理报修审核、登记来访者、查看本楼学生信息。学生进student/index.jsp只能看自己的信息、修改密码、查看考勤记录、提交报修申请。权限控制全靠 Session 里的role字段做 if-else 判断没有用过滤器Filter所以如果你直接在浏览器地址栏输admin/index.jsp只要 Session 里有任意用户登录就能看到页面——这是个权限漏洞但毕设答辩一般不会深究。如果你想做得严谨点可以在每个角色目录下加一个公共 JSP 文件用% include filecheckRole.jsp %的方式引入角色校验逻辑。!-- checkRole.jsp放在各角色目录下被同目录其他页面引入 -- % String role (String) session.getAttribute(role); if (role null || !admin.equals(role)) { response.sendRedirect(../login.jsp); return; } %这段代码的作用是如果 Session 里没有角色信息或者角色不匹配当前目录就踢回登录页。return不能省否则后面的页面代码还会继续执行。注意路径../login.jsp是相对当前 JSP 文件的如果你的目录结构不同要相应调整。3.3 学生注册流程与数据校验学生注册是唯一不需要登录就能访问的功能。注册页register.jsp收集学号、姓名、性别、学院、班级、密码等信息提交到RegisterServlet先查t_student表看学号是否已存在不存在才执行 INSERT。这里有个容易翻车的点学号字段t_stuNum在数据库里没有加 UNIQUE 约束所以如果你在 Servlet 里忘了做重复校验同一个学号能注册多次。我一般会在建表时就加上UNIQUE KEY uk_stuNum (t_stuNum)然后在 Servlet 里 catchSQLIntegrityConstraintViolationException给用户返回“该学号已注册”。// RegisterServlet.java 中的重复校验与插入 String stuNum request.getParameter(stuNum); // 先查重 String checkSql SELECT COUNT(*) FROM t_student WHERE t_stuNum?; ps conn.prepareStatement(checkSql); ps.setString(1, stuNum); rs ps.executeQuery(); if (rs.next() rs.getInt(1) 0) { request.setAttribute(msg, 该学号已注册请直接登录); request.getRequestDispatcher(register.jsp).forward(request, response); return; } // 再插入 String insertSql INSERT INTO t_student(t_stuNum,t_password,t_name,t_sex,t_stuClass,t_stuacademy) VALUES(?,?,?,?,?,?); ps conn.prepareStatement(insertSql); ps.setString(1, stuNum); ps.setString(2, request.getParameter(password)); ps.setString(3, request.getParameter(name)); ps.setString(4, request.getParameter(sex)); ps.setString(5, request.getParameter(stuClass)); ps.setString(6, request.getParameter(stuacademy)); ps.executeUpdate(); response.sendRedirect(login.jsp);参数说明t_stuNum是学号t_password是密码t_name是姓名t_sex是性别t_stuClass是班级t_stuacademy是院系。注意t_dormBuildId和t_dormName在注册阶段不填等管理员分配宿舍后再更新。注册成功后跳回登录页不自动登录这是文档里的流程你照做就行。4. 宿舍管理与组合查询管理员模块的增删改查与多条件筛选4.1 学生信息管理的分页查询实现系统管理员最常用的功能就是学生信息管理。文档里提到了“组合查询信息”意思是能按学号、姓名、班级、宿舍楼多个条件组合筛选。实现方式是在 JSP 页面放几个输入框和一个查询按钮提交到StudentListServletServlet 动态拼 SQL 的 WHERE 子句。// StudentListServlet.java 中的组合查询逻辑 String stuNum request.getParameter(stuNum); String name request.getParameter(name); String stuClass request.getParameter(stuClass); String dormBuildId request.getParameter(dormBuildId); StringBuilder sql new StringBuilder(SELECT * FROM t_student WHERE 11); ListObject params new ArrayList(); if (stuNum ! null !stuNum.trim().isEmpty()) { sql.append( AND t_stuNum LIKE ?); params.add(% stuNum.trim() %); } if (name ! null !name.trim().isEmpty()) { sql.append( AND t_name LIKE ?); params.add(% name.trim() %); } if (stuClass ! null !stuClass.trim().isEmpty()) { sql.append( AND t_stuClass ?); params.add(stuClass.trim()); } if (dormBuildId ! null !dormBuildId.trim().isEmpty()) { sql.append( AND t_dormBuildId ?); params.add(Integer.parseInt(dormBuildId.trim())); } // 分页处理 int page 1; int pageSize 10; if (request.getParameter(page) ! null) { page Integer.parseInt(request.getParameter(page)); } sql.append( LIMIT ?,?); params.add((page - 1) * pageSize); params.add(pageSize); ps conn.prepareStatement(sql.toString()); for (int i 0; i params.size(); i) { ps.setObject(i 1, params.get(i)); } rs ps.executeQuery();这里用WHERE 11是为了后面拼接 AND 条件方便不用判断是不是第一个条件。LIKE查询用%包裹参数实现模糊匹配但注意%要加在 Java 代码里不能写在 SQL 里否则 PreparedStatement 的参数替换会出问题。分页用LIMIT ?,?第一个参数是偏移量第二个是每页条数。查询结果存到request.setAttribute(studentList, list)然后 forward 到studentList.jsp渲染表格。4.2 宿舍楼与宿舍管理员的数据联动宿舍楼信息表t_dromBuild和宿舍管理员表t_dromAdmin通过t_dormBuildId关联。管理员在添加宿舍管理员时需要从t_dromBuild查出所有宿舍楼在下拉框里显示选中的t_dormBuildId存入t_dromAdmin表。这个联动逻辑在 JSP 里用 JSTL 或者脚本片段都能做。!-- addDormAdmin.jsp 中的宿舍楼下拉框 -- select namedormBuildId % Connection conn DBUtil.getConnection(); PreparedStatement ps conn.prepareStatement(SELECT * FROM t_dromBuild); ResultSet rs ps.executeQuery(); while (rs.next()) { % option value%rs.getInt(t_dormBuildId)% %rs.getString(t_dormName)% /option % } DBUtil.close(conn, ps, rs); % /select这种在 JSP 里直接写数据库查询的写法现在看确实不优雅但毕设场景下最直观——页面加载时就把下拉框数据查出来了不用额外写 Servlet 再转发。注意DBUtil.close()要放在循环外面否则第一次循环就把连接关了后面会报SQLException: Operation not allowed after ResultSet closed。这个坑我见过不止一个同学踩。4.3 报修审核与来访登记的状态流转宿舍管理员的报修审核功能本质是对一条报修记录更新状态字段。文档里没给报修表的详细结构但按常见做法会有一张t_repair表包含报修编号、学生学号、报修内容、报修时间、状态待审核/已通过/已驳回。宿舍管理员在页面点击“通过”或“驳回”提交到RepairAuditServlet执行 UPDATE 语句。// RepairAuditServlet.java 中的状态更新 String repairId request.getParameter(repairId); String status request.getParameter(status); // 1 通过2 驳回 String sql UPDATE t_repair SET status? WHERE repairId?; ps conn.prepareStatement(sql); ps.setString(1, status); ps.setInt(2, Integer.parseInt(repairId)); int rows ps.executeUpdate(); if (rows 0) { response.sendRedirect(repairList.jsp?msgauditSuccess); } else { response.sendRedirect(repairList.jsp?msgauditFail); }来访登记类似INSERT 一条记录到t_visitor表字段包括来访者身份证号、姓名、性别、电话、来访日期、被访学生宿舍楼编号。注意t_visitorId如果按文档定义成 INT(18)插入 18 位身份证号会报Out of range value所以我在 2.3 节建议改成 VARCHAR(18)。这个坑不提前说你调试时能卡半天。5. 避坑与排查JSP 项目里那些文档不会写的翻车现场5.1 中文乱码从数据库到浏览器的全链路排查现象登录页输入中文用户名提交后提示账号密码错误或者学生姓名在表格里显示成???。原因JSP 页面、Servlet、数据库连接、表字符集四个环节只要有一个没设 UTF-8中文就会丢。解决JSP 页面顶部加% page contentTypetext/html;charsetUTF-8 languagejava %Servlet 里request.setCharacterEncoding(UTF-8)和response.setContentType(text/html;charsetUTF-8)都要写数据库连接 URL 加?useUnicodetruecharacterEncodingutf8建库建表时指定utf8mb4。四个地方全对齐乱码基本就没了。5.2 Tomcat 启动报 404项目路径与 web.xml 配置现象Eclipse 里 Run on Server 后浏览器显示 404或者访问http://localhost:8080/项目名/login.jsp提示资源不存在。原因常见的是web.xml里welcome-file-list没配或者项目的 Context Root 跟你在地址栏输的不一致。解决在 Eclipse 项目属性 → Web Project Settings 里看 Context Root 是什么默认是项目名web.xml里加上welcome-filelogin.jsp/welcome-file如果改了web.xml记得在 Servers 面板里 Clean 一下 Tomcat否则缓存会让你怀疑人生。5.3 MySQL 连接超时连接池没关导致的 Too many connections现象系统跑一段时间后所有数据库操作都报Too many connections。原因每次数据库操作都DriverManager.getConnection()新建连接用完没close()连接数越积越多。解决封装一个DBUtil类在finally块里统一关闭ResultSet、PreparedStatement、Connection。如果并发量稍大可以引入 DBCP 或 C3P0 连接池但对毕设来说把 close 写对就够了。5.4 JSP 编译错误javax.servlet 包找不到现象Eclipse 里 JSP 文件满屏红叉提示The import javax.servlet cannot be resolved。原因项目 Build Path 里没有加 Tomcat 的servlet-api.jar。解决右键项目 → Build Path → Configure Build Path → Libraries → Add External JARs找到 Tomcat 安装目录下lib/servlet-api.jar加进来。注意不要把这个 jar 复制到WEB-INF/lib下否则 Tomcat 启动时会报类冲突。5.5 学生注册后登录失败密码字段长度截断现象学生注册时密码设了 15 位登录时输同样的密码却提示错误。原因t_password字段定义的是VARCHAR(20)但如果你的注册 Servlet 里没做长度校验而数据库实际字符集是 latin1一个中文字符占 2 字节密码里如果有中文20 字节可能只存得下 10 个字符。解决密码字段统一用英文数字组合或者把t_password改成VARCHAR(50)并确保字符集是 utf8mb4。6. 从能跑到能讲答辩演示的流程编排与代码走读技巧这套系统跑通之后真正的考验是答辩。老师不会看你代码写得多优雅但一定会让你演示一遍完整流程然后挑一个功能问你“这个是怎么实现的”。我的经验是提前把演示脚本写好按“管理员登录 → 添加宿舍楼 → 添加宿舍管理员 → 学生注册 → 学生登录查看信息 → 宿舍管理员处理报修 → 管理员组合查询”这条线走一遍每个步骤控制在 30 秒内全程不超过 5 分钟。演示时不要打开 Eclipse直接用浏览器操作避免 IDE 弹窗打断节奏。代码走读环节重点准备三个问题登录怎么区分三种角色答 Session role 参数 查不同表、组合查询怎么拼 SQL答 StringBuilder WHERE 11 PreparedStatement 防注入、数据库连接怎么管理答 DBUtil 封装 finally 关闭。这三个问题覆盖了这套系统的核心机制答清楚了老师基本不会再往深了问。如果你想让演示更稳可以提前在数据库里插几条测试数据比如一个系统管理员账号admin/123456、一个宿舍管理员账号dormAdmin/123456、一个学生账号2023001/123456演示时直接登录不用现场注册。还有一个技巧把web.xml里的session-config超时时间设长一点比如 60 分钟避免演示到一半 Session 过期被踢回登录页。这个翻车场景我见过学生正讲得起劲点下一个菜单突然跳回登录页场面非常尴尬。!-- web.xml 中设置 Session 超时 -- session-config session-timeout60/session-timeout /session-config从那以后我每次帮人调 JSP 项目都先把 Session 超时、字符集、数据库连接关闭这三件事检查一遍确认没问题再往下做功能。希望帮到你。本文还有配套的精品资源点击获取