ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Java Web宿舍管理系统:Servlet+JSP+MySQL高并发毕业设计实战

Java Web宿舍管理系统:Servlet+JSP+MySQL高并发毕业设计实战 简介这是一套面向计算机专业本科生的Java Web毕业设计实战项目聚焦高校学生宿舍管理场景提供开箱即用的完整系统解决方案。资源包含基于ServletJSPMySQL开发的学生宿舍管理系统源码及配套数据库脚本覆盖学生、寝室管理员、系统管理员三类角色权限支持学生信息维护、寝室分配、缺勤登记、床位状态查询等核心业务界面简洁、操作逻辑清晰适合作为课程设计或毕业设计参考与二次开发基础。压缩包共1315个文件主体为60个Java后端类、26个JSP页面、63个CSS与508个JS前端资源辅以SQL建库脚本、配置文件及少量图标资源整体体积仅3.74MB轻量易部署。目前已有496人学习下载资源结构规范含完整MVC分层代码、可直接导入IDE运行的工程目录以及清晰的角色登录入口与功能模块划分显著降低初学者环境搭建与调试门槛。1. 这不是又一个“能跑就行”的Java Web毕业设计它真能扛住300人并发查寝、缺勤统计秒出、三类角色权限不串台且MySQL表结构经得起答辩老师翻三遍你手头那份标着“高分毕业设计”“下载即用”的Java Web学生宿舍管理系统大概率正躺在某个压缩包里吃灰——因为90%的同名项目启动就报ClassNotFoundException: com.mysql.cj.jdbc.Driver登录页空白或者管理员删了学生记录后寝室分配状态直接错乱。但这次不一样这个源码包不是Demo级玩具它用ServletJSPMySQL原生栈落地了真实宿舍管理闭环——学生查自己床位和考勤流水、寝室管理员批量调寝并生成换宿单、系统管理员配置楼栋-楼层-房间三级树形结构、导出Excel缺勤报表时自动按周聚合、甚至登录失败5次后锁定账号15分钟。它没用Spring Boot自动装配来掩盖细节所有DAO层SQL手写带注释数据库建表语句明确区分student_info含身份证号加密字段、dorm_building带楼层排序序号、attendance_log含GPS打卡经纬度预留字段。适合两类人一是大三下刚学完JDBC想拿个扎实项目练手的同学二是需要快速交付院系级轻量级宿舍管理后台的教务老师。别被“毕业设计”四个字劝退——它的权限模型和事务边界比很多企业外包的小系统更干净。2. 从解压到首页可访问环境准备、数据库导入与Tomcat部署三步实操2.1 环境清单与版本锚点为什么必须用JDK 8u202 Tomcat 8.5.99 MySQL 5.7.32这个项目不是为新版本Java生态设计的。我试过用JDK 17启动web.xml里的servlet-class路径解析直接失败换成Tomcat 10javax.servlet.*包全报红——因为项目用的是Servlet 3.1规范而Tomcat 10默认走Jakarta EE 9包名已从javax.*升级为jakarta.*。最终验证通过的黄金组合是JDK 8u202非最新u版u231之后的JDBC驱动兼容性有坑 Tomcat 8.5.99官方最后稳定版支持Servlet 3.1且无Jakarta迁移问题 MySQL 5.7.32避免8.0的caching_sha2_password认证插件导致连接拒绝。提示MySQL安装时务必选择“Legacy Authentication Method”否则jdbc:mysql://localhost:3306/dorm?useSSLfalseserverTimezoneGMT%2B8连接字符串会因密码加密方式不匹配而卡死。2.2 数据库初始化执行dorm_db.sql前必须改的三处硬编码解压后找到/sql/dorm_db.sql文件别急着双击导入。打开它你会看到三处必须手动修改的位置第12行CREATE DATABASE dorm CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;→ 改成你本地MySQL实际创建的库名比如你习惯用dorm_system第47行INSERT INTO user_role (role_id, role_name, description) VALUES (1, 学生, 普通用户);→ 检查user_role表是否已存在若已存在则注释掉整段INSERT否则主键冲突第156行INSERT INTO dorm_building (building_id, building_name, total_floors, manager_id) VALUES (1, 1号公寓, 6, 1);→manager_id1指向admin_user表首条记录确保admin_user表在dorm_building之前执行SQL文件顺序已排好但Navicat等工具可能打乱执行顺序。执行成功后在MySQL命令行验证USE dorm; SELECT COUNT(*) FROM student_info; -- 应返回12条测试数据 SELECT role_name FROM user_role WHERE role_id 3; -- 应返回寝室管理员2.3 Tomcat部署war包构建与context.xml权限绕过关键配置项目根目录下没有现成war包需手动打包# 进入项目根目录含WEB-INF、src、sql等文件夹 cd /path/to/dorm-system # 编译Java源码注意class文件必须输出到WEB-INF/classes javac -encoding UTF-8 -d WEB-INF/classes -cp lib/*:. src/com/dorm/dao/*.java src/com/dorm/service/*.java src/com/dorm/servlet/*.java # 打包成war关键不能漏掉lib下的mysql-connector-java-5.1.47.jar jar -cvf dorm.war .将生成的dorm.war复制到$TOMCAT_HOME/webapps/目录下。启动Tomcat前必须修改$TOMCAT_HOME/conf/context.xml!-- 在Context标签内添加 -- Resource namejdbc/dormDB authContainer typejavax.sql.DataSource maxTotal20 maxIdle10 minIdle5 initialSize5 factoryorg.apache.tomcat.jdbc.pool.DataSourceFactory driverClassNamecom.mysql.cj.jdbc.Driver urljdbc:mysql://localhost:3306/dorm?useSSLfalseamp;serverTimezoneGMT%2B8amp;characterEncodingutf8mb4 usernameroot passwordyour_password validationQuerySELECT 1 testOnBorrowtrue/注意url中的必须写成amp;否则Tomcat解析XML失败validationQuery设为SELECT 1而非SELECT NOW()避免MySQL严格模式报错。启动Tomcat后访问http://localhost:8080/dorm/login.jsp输入默认账号学生stu001/123456寝室管理员dormadm/123456系统管理员admin/1234563. 三类角色权限拆解从URL拦截到JSP动态include的权限控制链3.1 web.xml中的Filter链LoginFilter如何拦截未登录请求项目没用Shiro或Spring Security而是用原生Filter实现权限网关。核心在web.xml的Filter配置filter filter-nameLoginFilter/filter-name filter-classcom.dorm.filter.LoginFilter/filter-class /filter filter-mapping filter-nameLoginFilter/filter-name url-pattern/student/*/url-pattern url-pattern/dormadm/*/url-pattern url-pattern/admin/*/url-pattern /filter-mappingLoginFilter.doFilter()逻辑极简但有效public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest request (HttpServletRequest) req; HttpServletResponse response (HttpServletResponse) resp; // 检查session中是否存在user对象登录后存入 if (request.getSession().getAttribute(user) null) { // 关键重定向到login.jsp并携带原始请求URL作为参数 String originalUrl request.getRequestURI() ? request.getQueryString(); response.sendRedirect(request.getContextPath() /login.jsp?redirect URLEncoder.encode(originalUrl, UTF-8)); return; } chain.doFilter(req, resp); }参数说明redirect参数让登录成功后能跳回原页面如学生点击“我的考勤”链接后登录自动回到考勤页避免用户重复操作。3.2 JSP页面级权限用c:if动态加载不同导航栏每个角色首页/student/index.jsp,/dormadm/index.jsp,/admin/index.jsp都包含统一头部但导航栏内容由Session中的userRole决定!-- /common/header.jsp -- c:choose c:when test${sessionScope.user.roleId 1} !-- 学生角色只显示个人信息、考勤查询、报修入口 -- lia href${pageContext.request.contextPath}/student/profile.jsp个人信息/a/li lia href${pageContext.request.contextPath}/student/attendance.jsp考勤记录/a/li lia href${pageContext.request.contextPath}/student/repair.jsp在线报修/a/li /c:when c:when test${sessionScope.user.roleId 2} !-- 寝室管理员增加调寝、卫生检查、空床位管理 -- lia href${pageContext.request.contextPath}/dormadm/transfer.jsp床位调整/a/li lia href${pageContext.request.contextPath}/dormadm/check.jsp卫生检查/a/li lia href${pageContext.request.contextPath}/dormadm/vacancy.jsp空床位管理/a/li /c:when c:otherwise !-- 系统管理员全功能入口 -- lia href${pageContext.request.contextPath}/admin/user.jsp用户管理/a/li lia href${pageContext.request.contextPath}/admin/building.jsp楼栋管理/a/li lia href${pageContext.request.contextPath}/admin/report.jsp统计报表/a/li /c:otherwise /c:choose注意roleId值来自数据库user_role表学生1、寝室管理员2、系统管理员3硬编码在JSP中虽不优雅但对毕业设计足够清晰。3.3 DAO层SQL注入防护PreparedStatement参数化查询的强制实践所有涉及用户输入的DAO方法如StudentDao.findByStuId(String stuId)均使用PreparedStatement杜绝拼接SQLpublic Student findStudentByStuId(String stuId) throws SQLException { String sql SELECT * FROM student_info WHERE stu_id ? AND status active; PreparedStatement ps connection.prepareStatement(sql); ps.setString(1, stuId); // 关键参数占位符绑定非字符串拼接 ResultSet rs ps.executeQuery(); // ...结果集处理 }对比反面案例项目中已被删除的旧代码// ❌ 危险已移除 String sql SELECT * FROM student_info WHERE stu_id stuId ;血泪经验答辩时老师常问“如果stuId传入 OR 11会怎样”用PreparedStatement的回答能直接加分。4. 避坑指南五个让90%新手卡住的致命细节与修复方案4.1 现象登录页CSS样式全失效按钮文字堆叠成一团原因项目JSP中引用CSS路径为link relstylesheet hrefcss/style.css但Tomcat部署war包后静态资源路径实际为/dorm/css/style.css而浏览器请求的是根路径/css/style.css。解决在所有JSP顶部添加base href${pageContext.request.contextPath}/或统一用link relstylesheet href${pageContext.request.contextPath}/css/style.css。4.2 现象学生登录后点击“考勤记录”页面报HTTP Status 500 – java.lang.NullPointerException原因AttendanceServlet中调用attendanceService.listByStuId(stuId)时stuId从Session中取值但部分学生账号未关联考勤记录listByStuId()返回null后续for循环遍历时NPE。解决在Service层增加判空public ListAttendance listByStuId(String stuId) { if (stuId null || stuId.trim().isEmpty()) { return new ArrayList(); // 返回空集合非null } // ...原有查询逻辑 }4.3 现象MySQL导入dorm_db.sql时报错ERROR 1067 (42000): Invalid default value for create_time原因MySQL 5.7默认开启STRICT_TRANS_TABLES模式而SQL文件中create_time DATETIME DEFAULT 0000-00-00 00:00:00违反严格模式。解决执行SET GLOBAL sql_mode(SELECT REPLACE(sql_mode,STRICT_TRANS_TABLES,));临时关闭严格模式或修改SQL中该字段为DEFAULT CURRENT_TIMESTAMP。4.4 现象Tomcat启动后控制台刷屏SEVERE: Servlet.service() for servlet [jsp] in context with path [/dorm] threw exception原因WEB-INF/lib下存在两个不同版本的JSTL jar如jstl-1.2.jar和standard.jar导致EL表达式解析冲突。解决删除standard.jar仅保留jstl-1.2.jar并在web.xml中声明JSP版本jsp-config jsp-property-group url-pattern*.jsp/url-pattern el-ignorefalse/el-ignore /jsp-property-group /jsp-config4.5 现象导出Excel报表时中文乱码显示为??原因ExportServlet中设置响应头response.setContentType(application/vnd.ms-excel;charsetUTF-8)但Excel 2007实际需要charsetGBK才能正确识别中文。解决改为response.setContentType(application/vnd.ms-excel;charsetGBK);并在生成Excel时用HSSFWorkbook非XSSFWorkbook以兼容老版本Excel。5. 真实业务场景加固给缺勤统计加时间窗口校验、为调寝操作加事务回滚点5.1 缺勤统计的业务时间窗防止跨学期数据污染报表原始AttendanceService.generateWeeklyReport()方法直接查attendance_log表所有记录但实际需求是“统计本学期第12周考勤”。需在DAO层增加时间范围约束// 修改AttendanceDao.java中的查询SQL String sql SELECT stu_id, COUNT(*) as absent_count FROM attendance_log WHERE check_status absent AND check_date BETWEEN ? AND ? // 新增时间范围占位符 GROUP BY stu_id; PreparedStatement ps conn.prepareStatement(sql); ps.setDate(1, Date.valueOf(2024-05-20)); // 本学期第12周起始日 ps.setDate(2, Date.valueOf(2024-05-26)); // 本学期第12周结束日技巧在admin/report.jsp中增加日期选择器将选中的周范围传入Servlet避免硬编码。5.2 调寝操作的原子性保障用JDBC事务包裹床位变更与日志写入DormAdmServlet.transferBed()方法原为两步独立SQL先更新student_info.dorm_id再插入dorm_log。若第一步成功第二步失败会导致学生已调寝但无操作记录。加固方案connection.setAutoCommit(false); // 关闭自动提交 try { // 步骤1更新学生宿舍ID String updateSql UPDATE student_info SET dorm_id ? WHERE stu_id ?; PreparedStatement ps1 connection.prepareStatement(updateSql); ps1.setString(1, newDormId); ps1.setString(2, stuId); ps1.executeUpdate(); // 步骤2写入调寝日志 String logSql INSERT INTO dorm_log (stu_id, old_dorm_id, new_dorm_id, operator_id, operate_time) VALUES (?, ?, ?, ?, NOW()); PreparedStatement ps2 connection.prepareStatement(logSql); ps2.setString(1, stuId); ps2.setString(2, oldDormId); ps2.setString(3, newDormId); ps2.setString(4, operatorId); ps2.executeUpdate(); connection.commit(); // 两步都成功才提交 } catch (SQLException e) { connection.rollback(); // 任一步失败则回滚 throw e; } finally { connection.setAutoCommit(true); // 恢复自动提交 }注意dorm_log表必须为InnoDB引擎MyISAM不支持事务。5.3 寝室管理员权限的二次校验防止URL硬编码越权访问当前/dormadm/transfer.jsp页面仅靠Filter拦截但若用户手动构造URL如/dormadm/transfer.jsp?targetStuIdstu999仍可能越权操作。需在Servlet中增加角色与数据归属校验// DormAdmServlet.java String targetStuId request.getParameter(targetStuId); // 获取当前登录的寝室管理员负责的楼栋ID String managedBuilding (String) session.getAttribute(managedBuilding); // 查询目标学生所在楼栋 String stuBuilding studentDao.findBuildingByStuId(targetStuId); if (!managedBuilding.equals(stuBuilding)) { request.setAttribute(error, 无权操作其他楼栋学生); request.getRequestDispatcher(/dormadm/error.jsp).forward(request, response); return; }从那以后我每次做权限校验都强制走一遍“前端拦截→URL参数校验→数据库归属校验”三层过滤哪怕多写20行代码——答辩老师盯着你问“如果有人改URL参数呢”时这三层就是你的后悔药。希望帮到你。本文还有配套的精品资源点击获取
返回列表