news 2026/9/12 22:43:43

JavaWeb宿舍管理系统:Servlet+MySQL+Layui轻量架构实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
JavaWeb宿舍管理系统:Servlet+MySQL+Layui轻量架构实战

简介:这是一套面向计算机相关专业学生与初学者的毕业设计级宿舍管理系统实战项目,基于JavaWeb技术栈实现高校宿舍管理核心功能,解决人员信息维护、房间分配、报修处理等实际业务场景需求,适合作为课程设计、毕设选题或Java全栈入门进阶实践。资源包共372个文件,含68个Java源码(涵盖Controller/Service/DAO三层结构)、62个JSP页面(结合JSTL与EL表达式实现动态展示)、34张演示截图及1个SQL建库脚本,辅以136个编译后Class文件和13个依赖Jar包,整体压缩包大小29.27MB。已有790人学习下载,项目采用MVC架构,目录结构规范清晰,包含constant常量、filter过滤器、utils工具类等完整模块,且所有代码经Tomcat10+JDK1.8+MySQL8.0环境实测可运行,附带详细项目说明与开发环境配置清单,便于快速部署与二次开发。

1. 这不是又一个“学生练手项目”:JavaWeb + MySQL + Layui 宿舍管理系统的真实落地价值

你下载的这个宿舍管理系统.zip,表面看是「源码+数据库+截图+说明」的常规打包,但真正值得深挖的是它背后隐含的企业级轻量管理系统的最小可行架构范式。它不依赖 Spring Boot 自动装配、不引入 Redis 缓存、不走微服务拆分,却用最朴素的 Servlet/JSP + JDBC + Layui 组合,完整覆盖了用户登录鉴权、楼栋/房间/学生/管理员四维数据建模、入住退宿状态流转、费用明细记录、权限分级(宿管员仅能操作本楼栋)等真实业务闭环。对刚学完 JDBC 和 HTML/CSS 的开发者,这是能跑通、能改、能部署到 Tomcat 8.5+ 的第一套「有业务语义」的系统;对三年以上 Java 开发者,它是一面镜子——你能快速识别出哪些 DAO 层写法已过时(如手动拼接 SQL)、哪些 Layui 表单校验没做防重复提交、哪些 MySQL 字段类型选择埋了隐患(比如用 VARCHAR(20) 存手机号而非 CHAR(11))。它解决的不是“怎么写 Hello World”,而是“如何让一个带状态、带角色、带事务的 Web 系统在 Windows Server 或 CentOS 上稳定运行三个月不崩”。


2. 拆解三层结构:为什么选 JavaWeb 而非 Spring Boot?Layui 为何仍是宿舍类后台首选?

2.1 JavaWeb 技术栈选型的现实约束与合理性

这套系统坚持使用原生 Servlet + JSP + JDBC,而非当下更主流的 Spring Boot,根本原因在于部署环境兼容性与运维成本控制。很多高校信息中心或小型物业公司仍在使用 JDK 1.8 + Tomcat 7/8.0.x 的老旧服务器,而 Spring Boot 2.7+ 要求 JDK 11+,且内嵌 Tomcat 版本升级后常与现有 Nginx 反向代理规则冲突。JavaWeb 方案直接编译为 WAR 包,丢进 Tomcat/webapps 目录即可启动,无需额外配置 JVM 参数或 Actuator 端点。更重要的是,其 DAO 层虽未用 MyBatis,但通过BaseDao封装了通用 CRUD 方法,例如:

// src/com/dao/BaseDao.java public class BaseDao { public static Connection getConnection() throws SQLException { // 从 properties 文件读取 db.url, db.username, db.password String url = PropertiesUtil.getProperty("db.url"); return DriverManager.getConnection(url, PropertiesUtil.getProperty("db.username"), PropertiesUtil.getProperty("db.password")); } }

提示:PropertiesUtil是自定义工具类,读取src/db.properties,而非硬编码数据库连接字符串。这是规避生产环境密码泄露的第一道防线,也是新手最容易忽略的安全基线。

对比 Spring Boot 的application.yml,这种写法看似原始,但在无 Maven 依赖管理、无自动配置能力的旧服务器上反而更可控——你清楚知道每一行代码何时执行、哪个 jar 包被加载、连接池是否真的生效。

2.2 MySQL 数据库设计中的业务语义落地

该系统数据库共 6 张表,核心是student(学生)、dormitory(宿舍)、dorm_building(楼栋)、admin_user(管理员)、fee_record(费用)、dorm_assignment(分配记录)。其中关键设计点在于:

  • dorm_assignment表同时记录student_iddorm_idassign_datestatus(1=入住,0=退宿),用单表实现状态机,避免为“历史入住记录”单独建表;
  • dormitory表中room_number类型为VARCHAR(10),但实际值如301A205,说明系统需支持字母+数字混合编号,这直接影响 Layui 表格排序逻辑(纯字符串排序A10<A2);
  • fee_record表的fee_type字段用TINYINT存储枚举值(1=水电费,2=维修费,3=押金),而非VARCHAR,既节省空间,又防止前端传入非法字符串。
-- 创建 dorm_assignment 表(关键状态流转表) CREATE TABLE `dorm_assignment` ( `id` INT PRIMARY KEY AUTO_INCREMENT, `student_id` INT NOT NULL, `dorm_id` INT NOT NULL, `assign_date` DATE NOT NULL, `status` TINYINT NOT NULL DEFAULT 1 COMMENT '1:入住,0:退宿', `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (`student_id`) REFERENCES `student`(`id`), FOREIGN KEY (`dorm_id`) REFERENCES `dormitory`(`id`) );

注意:FOREIGN KEY在 MySQL 中需使用 InnoDB 引擎,若导入时提示“Cannot add or update a child row”,大概率是student_iddorm_id值在父表中不存在,此时应先检查studentdormitory表数据是否已初始化。

2.3 Layui 作为前端框架的不可替代性

Layui 被选中,不是因为“轻量”,而是因为它天然适配宿舍管理这类表单密集、操作路径固定、无需复杂路由的后台场景。其layui.form.render()可动态重载 select 下拉框选项,layui.table.render()支持toolbar: '#toolbarDemo'自定义工具栏按钮,这些特性让“批量调整房间状态”、“导出某楼栋所有学生名单”等功能开发效率远超手写 jQuery。更重要的是,Layui 的日期控件laydate默认支持max: 'today'设置最大可选日期,恰好满足“退宿日期不能晚于今天”的业务强约束:

// dorm-edit.jsp 中的退宿日期控件 layui.use('laydate', function(){ var laydate = layui.laydate; laydate.render({ elem: '#leaveDate', max: 'today', // 关键:禁止选择未来日期 format: 'yyyy-MM-dd', trigger: 'click' }); });

提示:max: 'today'是 Layui 2.8+ 的语法,若你下载的源码中layui/lay/modules/laydate.js版本低于此,需手动替换为max: new Date().toISOString().split('T')[0],否则控件将失效。


3. 本地跑通全流程:从数据库初始化到 Tomcat 部署的 7 个关键步骤

3.1 MySQL 数据库导入与字符集确认

第一步不是解压 ZIP,而是确认 MySQL 服务已启动且字符集为utf8mb4。执行以下命令验证:

mysql -u root -p -e "SHOW VARIABLES LIKE 'character_set%';"

输出中character_set_servercollation_server必须为utf8mb4utf8mb4_unicode_ci。若非如此,需修改my.cnf(Linux)或my.ini(Windows):

[mysqld] character-set-server=utf8mb4 collation-server=utf8mb4_unicode_ci

然后重启 MySQL 服务。接着导入数据库:

# 创建数据库(显式指定字符集) mysql -u root -p -e "CREATE DATABASE dorm_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;" # 导入 SQL 文件(假设文件名为 dorm_db.sql,位于当前目录) mysql -u root -p dorm_db < dorm_db.sql

注意:dorm_db.sql文件中若包含CREATE DATABASE语句,需先删除该行再导入,否则会因权限问题失败。常见错误ERROR 1044 (42000): Access denied for user即源于此。

3.2 修改数据库连接配置

打开src/db.properties,按实际环境修改:

db.url=jdbc:mysql://localhost:3306/dorm_db?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai db.username=root db.password=your_actual_password
  • serverTimezone=Asia/Shanghai是 MySQL 8.0+ 必加参数,否则java.sql.SQLException: The server time zone value '...' is unrecognized错误必现;
  • 若 MySQL 为 5.7 版本,可删去serverTimezone,但必须确保系统时区与 MySQL 一致(SELECT NOW();查看)。

3.3 Eclipse/IDEA 中正确配置 Web 工程

在 IDE 中新建 Dynamic Web Project,不要勾选“Generate web.xml deployment descriptor”—— 因为该系统使用web.xml手动配置 Servlet 映射,而非注解方式。将src下所有.java文件复制到src目录,WebContent下所有文件(含WEB-INF/web.xmljs/css/images/)复制到WebContent目录。关键配置在web.xml

<servlet> <servlet-name>LoginServlet</servlet-name> <servlet-class>com.servlet.LoginServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>LoginServlet</servlet-name> <url-pattern>/login</url-pattern> </servlet-mapping>

提示:<url-pattern>必须与 JSP 表单的action="/login"完全一致,大小写敏感。若页面提交后跳转 404,90% 是此处路径不匹配。

3.4 Tomcat 8.5+ 部署与端口检查

将工程导出为 WAR 包(Eclipse:右键 → Export → WAR file),放入Tomcat/webapps/目录。启动 Tomcat 后,访问http://localhost:8080/your_project_name/login.jsp。若出现空白页或 500 错误,立即检查Tomcat/logs/catalina.out,搜索Caused by:关键字。常见问题包括:

错误现象根本原因解决方案
ClassNotFoundException: com.mysql.cj.jdbc.DriverMySQL Connector/J 驱动未放入WEB-INF/lib/下载mysql-connector-java-8.0.33.jar,复制到WEB-INF/lib/
HTTP Status 404 – /xxx/login.jspWAR 包名与访问路径不一致访问http://localhost:8080/ROOT/login.jsp(若 WAR 名为ROOT.war
java.lang.NullPointerException at com.dao.BaseDao.getConnectiondb.properties未被正确加载确认PropertiesUtilgetClass().getClassLoader().getResourceAsStream("db.properties")返回非 null

3.5 登录功能验证与账号初始化

默认管理员账号通常在dorm_db.sql中已插入,查找类似语句:

INSERT INTO `admin_user` VALUES (1,'admin','e10adc3949ba59abbe56e057f20f883e','超级管理员',1,'2023-01-01 00:00:00');

密码e10adc3949ba59abbe56e057f20f883e是 MD5(123456),即初始密码为123456。若登录失败,用 MySQL 命令行重置:

UPDATE admin_user SET password = 'e10adc3949ba59abbe56e057f20f883e' WHERE username = 'admin';

注意:该系统未做密码盐值加密,生产环境必须替换为 BCrypt 或 SM3 加密,否则admin账号极易被撞库。


4. 关键功能调试:Layui 表格渲染、跨表查询、状态变更事务处理

4.1 Layui 表格动态加载学生列表并绑定操作列

学生管理页student-list.jsp使用 Layui Table 渲染,其核心是data属性指向后端 Servlet:

<table id="studentTable" lay-filter="studentTable"></table> <script> layui.use(['table'], function(){ var table = layui.table; table.render({ elem: '#studentTable', url: '/StudentListServlet', // 后端返回 JSON 数据 cols: [[ {field:'id', title:'学号', width:100}, {field:'name', title:'姓名', width:120}, {field:'dormName', title:'所在宿舍', width:150}, // 来自 JOIN 查询 {title:'操作', toolbar:'#barDemo', width:180} ]], page: true }); }); </script>

后端StudentListServlet必须返回标准 JSON 格式:

// StudentListServlet.java protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { List<StudentVO> list = studentService.listAllWithDorm(); // JOIN dormitory 表 JSONObject result = new JSONObject(); result.put("code", 0); result.put("msg", ""); result.put("count", list.size()); result.put("data", list); // list 中每个 StudentVO 有 dormName 字段 response.setContentType("application/json;charset=UTF-8"); response.getWriter().write(result.toString()); }

提示:StudentVO是专门用于表格展示的 VO 类,包含dormName字段,而非直接返回Student实体类。这是为避免 N+1 查询,也是 Layui Table 分页时只查一页数据的关键优化。

4.2 入住/退宿状态变更的事务一致性保障

DormAssignmentServlet处理入住请求时,必须保证“更新学生表状态”与“插入分配记录”在同一事务中:

Connection conn = null; PreparedStatement ps1 = null, ps2 = null; try { conn = BaseDao.getConnection(); conn.setAutoCommit(false); // 关键:开启事务 // 步骤1:更新 student 表的 dorm_status ps1 = conn.prepareStatement("UPDATE student SET dorm_status = ? WHERE id = ?"); ps1.setInt(1, 1); // 1=已入住 ps1.setInt(2, studentId); ps1.executeUpdate(); // 步骤2:插入 dorm_assignment 记录 ps2 = conn.prepareStatement("INSERT INTO dorm_assignment(student_id, dorm_id, status) VALUES(?, ?, ?)"); ps2.setInt(1, studentId); ps2.setInt(2, dormId); ps2.setInt(3, 1); ps2.executeUpdate(); conn.commit(); // 提交事务 } catch (Exception e) { if (conn != null) conn.rollback(); // 任一失败则回滚 throw e; } finally { // 关闭资源 }

注意:若忘记conn.setAutoCommit(false),两个 SQL 将各自提交,导致学生状态已更新但分配记录未写入,数据不一致。

4.3 MySQL 中处理宿舍空闲率统计的子查询写法

首页需显示各楼栋空闲房间数,SQL 不能简单COUNT(*),而要排除已分配房间:

SELECT b.name AS building_name, COUNT(d.id) AS total_rooms, COUNT(d.id) - COALESCE( (SELECT COUNT(*) FROM dorm_assignment a WHERE a.dorm_id = d.id AND a.status = 1), 0 ) AS free_rooms FROM dorm_building b LEFT JOIN dormitory d ON b.id = d.building_id GROUP BY b.id, b.name;

此查询在IndexServlet中执行,结果封装为BuildingStat对象传给 JSP。若发现空闲数恒为 0,检查dorm_assignment.status = 1是否真有数据——很多演示数据只插入了status = 0(退宿)记录。


5. 生产级加固与性能陷阱规避:从源码到上线的 5 个硬核动作

5.1 替换 JDBC 连接为 HikariCP 连接池

原生DriverManager.getConnection()在高并发下会创建大量物理连接,必须替换。在pom.xml中添加:

<dependency> <groupId>com.zaxxer</groupId> <artifactId>HikariCP</artifactId> <version>5.0.1</version> </dependency>

然后重写BaseDao.getConnection()

private static HikariConfig config = new HikariConfig(); static { config.setJdbcUrl("jdbc:mysql://localhost:3306/dorm_db?..."); config.setUsername("root"); config.setPassword("pwd"); config.addDataSourceProperty("cachePrepStmts", "true"); config.addDataSourceProperty("prepStmtCacheSize", "250"); } private static HikariDataSource ds = new HikariDataSource(config); public static Connection getConnection() throws SQLException { return ds.getConnection(); // 复用连接池 }

提示:prepStmtCacheSize设为 250 可显著提升PreparedStatement执行速度,尤其对频繁调用的SELECT * FROM student WHERE id = ?类查询。

5.2 Layui 日期控件位置偏移的 CSS 强制修正

Layui 2.8 的laydate在某些浏览器中点击后日历面板位置异常(如出现在屏幕顶部)。在dorm-edit.jsp底部添加:

<style> .laydate-main-list{z-index:999999 !important;} .laydate-container{position:fixed !important;} </style>

此 CSS 强制提升日历层级并固定定位,比修改laydate.js源码更安全。

5.3 MySQL 防止慢查询的索引补全清单

对高频查询字段添加复合索引,执行以下 SQL:

-- 学生按宿舍查询(JOIN dorm_assignment) ALTER TABLE dorm_assignment ADD INDEX idx_student_dorm_status (student_id, dorm_id, status); -- 费用按学生+时间范围查询 ALTER TABLE fee_record ADD INDEX idx_student_time (student_id, create_time); -- 宿舍按楼栋+房间号查询(WHERE building_id = ? AND room_number = ?) ALTER TABLE dormitory ADD INDEX idx_building_room (building_id, room_number);

注意:EXPLAIN SELECT ...命令必须对每个核心查询执行,确认typerefrange,而非ALL(全表扫描)。

5.4 Tomcat 内存溢出防护配置

Tomcat/bin/catalina.sh(Linux)或catalina.bat(Windows)中添加 JVM 参数:

# Linux catalina.sh 第 200 行附近添加 JAVA_OPTS="-Xms512m -Xmx1024m -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m"
  • -Xms512m避免频繁 GC;
  • -XX:MaxMetaspaceSize=512m防止加载过多 JSP 编译类导致 Metaspace OOM。

5.5 日志统一输出到文件而非控制台

修改log4j.properties(若存在)或添加logback.xmlWEB-INF/classes/

<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>logs/dorm-system.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>logs/dorm-system.%d{yyyy-MM-dd}.%i.log</fileNamePattern> </rollingPolicy> </appender> <root level="INFO"> <appender-ref ref="FILE"/> </root>

确保logs/目录在 Tomcat 启动用户下有写权限,否则日志无法生成。


Layui 表格的done回调函数中加入console.log(res)并观察res.count是否与数据库总记录数一致,这是验证分页 SQL 正确性的最快方法。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/12 22:41:12

OFDM系统中BPSK调制的SNR定义与校准方法

简介&#xff1a;本资源是一份面向通信工程专业本科生及MATLAB初学者的OFDM系统仿真学习材料&#xff0c;聚焦BPSK调制下OFDM在AWGN信道中的信噪比性能分析&#xff0c;助力理解数字通信系统建模与误码率评估核心流程。压缩包共7个MATLAB脚本文件&#xff08;.m&#xff09;&am…

作者头像 李华
网站建设 2026/9/12 22:36:50

车牌检测实战:基于YOLOv5/v7/v8的训练与TensorRT部署全解析

简介&#xff1a;面向毕业设计与智能交通应用场景&#xff0c;这套车牌检测代码基于YOLOv5、YOLOv7、YOLOv8三种主流目标检测框架实现&#xff0c;支持多达十二种不同类型的车牌识别&#xff0c;公开测试环境下准确率达到百分之九十九点五&#xff0c;可帮助开发者快速搭建车牌…

作者头像 李华
网站建设 2026/9/12 22:36:47

AI写作工具如何解决文科写作三大痛点

1. 文科写作的痛点与AI解决方案作为一名长期与文字打交道的文科研究者&#xff0c;我深刻理解学术写作中的三大困境&#xff1a;论证单薄、案例匮乏、表达平庸。传统写作模式下&#xff0c;我们需要花费大量时间在图书馆翻阅资料&#xff0c;手动整理文献卡片&#xff0c;这种低…

作者头像 李华
网站建设 2026/9/12 22:35:46

无人机图像数据集训练实战:YOLOv8小目标检测与切图调优指南

简介&#xff1a;面向无人机目标检测这一细分方向&#xff0c;这份数据集围绕四千余张业余无人机拍摄的实景照片构建&#xff0c;素材常见于大疆精灵等消费级无人机&#xff0c;并特意纳入非无人机及外观相似的干扰目标&#xff0c;适合训练能够区分真假无人机的检测模型。压缩…

作者头像 李华
网站建设 2026/9/12 22:34:49

C#调用PaddleOCR实现验证码识别的端到端方案

简介&#xff1a;这是一份面向C#开发者与OCR技术学习者的PaddleInference实战Demo资源&#xff0c;聚焦于轻量级验证码图像识别场景&#xff0c;适用于需在Windows桌面端集成OCR能力的工程实践或课程设计。资源基于VS2022.NET 4.8开发&#xff0c;整合OpenCvSharp4与Sdcb.Paddl…

作者头像 李华