ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Java宿舍管理系统毕设实战:权限控制与事务一致性设计

Java宿舍管理系统毕设实战:权限控制与事务一致性设计

简介:这是一套基于Java技术栈开发的完整学生宿舍管理系统毕业设计项目源码,面向计算机专业本科生及Java初学者,解决高校宿舍管理中学生、楼宇、宿舍、入住、宿管等多角色协同管理的实际需求。资源包共661个文件,涵盖35个核心Java类、400个前端交互JS脚本、46个CSS样式文件、28个Less/SCSS预编译样式、8个XML配置与SQL建表脚本,以及配套HTML页面、测试类、配置YML和少量操作录屏MP4,整体72.37MB,结构清晰体现SpringBoot+MySQL+Bootstrap三层架构典型实践。已有468人学习下载,提供开箱即用的管理员、宿管、学生三端功能模块,含全套增删改查、Excel批量导入导出、验证码登录、多环境数据库适配(MySQL5/8双版本)及完整可运行工程结构,适合课程设计、毕设参考与Java Web全栈能力训练。

1. 学生宿舍管理系统:为什么一个“老掉牙”的毕设,反而最容易在答辩现场被追问到哑口无言?

你手里的“基于Java的学生宿舍管理系统”,绝不是一份简单的增删改查练习。它表面是课程设计、毕业设计的常规选题,实则是一块检验工程能力的试金石——导师真正想看的,不是你能不能把学生信息存进数据库,而是你能否在“宿舍”这个高度受限、强规则、多角色、易冲突的真实业务场景里,把权限边界划清楚、把调宿逻辑跑通、把夜间查寝的时效性扛住、把维修报修的闭环做实。很多同学用Spring Boot搭个CRUD界面就交差,结果答辩时被问:“学生A申请换到302,但302当前已满员且有未处理的维修单,系统是直接拒绝、排队等待,还是自动触发空房调度?你的数据库约束和事务隔离级别怎么支撑这个判断?”——当场卡壳。这套方案专为这类“看似简单、一碰就碎”的真实交付场景而生:它不堆砌高大上技术,但每一步都经得起推敲;它提供完整可运行的Java源码,更关键的是,它把“为什么这么设计”“哪里容易翻车”“验收时重点看什么”全摊开写清楚。适合正在赶毕设/课设、需要一份能过审、能讲清、能演示、还能应对深度提问的硬核参考方案。

2. 总体架构设计:三层结构与四个核心模块的职责划分

本系统采用经典的分层架构,严格遵循关注点分离原则,避免业务逻辑与数据访问、表现层混杂。整体分为表现层(Web)、业务逻辑层(Service)、数据访问层(DAO),各层之间通过接口解耦,便于单元测试与后期维护。整个系统围绕宿舍管理的核心业务流展开,划分为四个高内聚、低耦合的模块:学生信息管理模块(负责学生基础档案、学籍状态、入住关联)、宿舍资源管理模块(涵盖楼栋、楼层、房间、床位的静态配置与动态容量控制)、住宿业务流程模块(覆盖入住登记、调宿申请、退宿办理、查寝记录等全生命周期操作)、后勤支持模块(处理维修报修、费用缴纳、公告发布等支撑性功能)。这种划分不是为了图形式,而是为了精准对应高校宿舍管理的实际组织分工——比如维修工只关心“后勤支持模块”里的报修单状态,辅导员则聚焦于“住宿业务流程模块”中的查寝异常汇总。所有模块均通过统一的Result<T>响应体封装返回数据,前端无需解析多种格式,降低联调成本。

2.1 数据库设计:从ER模型到MySQL物理表的关键取舍

数据库设计是本系统稳定性的基石。我们摒弃了过度规范化导致的复杂JOIN,也拒绝反规范化带来的数据一致性风险,采用适度规范化的第三范式(3NF)设计。核心实体包括student(学生)、dorm_building(楼栋)、dorm_room(房间)、dorm_bed(床位)、repair_order(维修单)等。其中最关键的取舍在于床位状态的建模方式:早期方案曾尝试用bed_status ENUM('vacant', 'occupied', 'under_repair')字段,但很快发现无法满足“同一床位在不同时间点存在多个并行状态”的业务需求(例如:某床位当前被占用,但已提交维修申请,且该维修申请尚未被受理)。最终采用独立的状态快照表bed_status_log,记录每次状态变更的时间、操作人、原因及有效期,主表dorm_bed仅保留最新有效状态。这样既保证了查询效率(主表状态字段用于快速筛选),又保留了完整的审计追溯能力。

-- dorm_bed 表(精简关键字段) CREATE TABLE `dorm_bed` ( `id` BIGINT PRIMARY KEY AUTO_INCREMENT, `room_id` BIGINT NOT NULL COMMENT '所属房间ID', `bed_number` VARCHAR(10) NOT NULL COMMENT '床号,如A1, B2', `current_status` TINYINT NOT NULL DEFAULT 1 COMMENT '当前状态:1-空闲,2-已入住,3-维修中', `last_updated` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, INDEX `idx_room_status` (`room_id`, `current_status`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- bed_status_log 表(状态变更日志) CREATE TABLE `bed_status_log` ( `id` BIGINT PRIMARY KEY AUTO_INCREMENT, `bed_id` BIGINT NOT NULL COMMENT '床位ID', `status_before` TINYINT NOT NULL COMMENT '变更前状态', `status_after` TINYINT NOT NULL COMMENT '变更后状态', `operator_id` BIGINT NOT NULL COMMENT '操作人ID(学生/管理员)', `reason` VARCHAR(200) COMMENT '变更原因', `valid_from` DATETIME NOT NULL COMMENT '生效时间', `valid_to` DATETIME COMMENT '失效时间,NULL表示永久有效', `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, INDEX `idx_bed_time` (`bed_id`, `valid_from`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

提示:dorm_bed.current_status字段是业务高频查询字段,必须建立复合索引idx_room_status。而bed_status_log表因需按时间范围查询历史,idx_bed_time索引至关重要。线上环境务必禁用SELECT *,所有查询必须明确指定所需字段,避免因表结构扩展导致性能陡降。

2.2 权限控制体系:RBAC模型在宿舍场景下的落地实践

宿舍管理系统涉及学生、辅导员、宿管员、维修工、系统管理员五类角色,权限粒度需精确到按钮级。我们采用改进的RBAC(基于角色的访问控制)模型,但未引入过于复杂的“权限-角色-用户”三级映射,而是将权限(Permission)直接绑定到角色(Role),并通过@PreAuthorize注解在Controller层进行方法级校验,兼顾安全性与开发效率。关键设计点在于角色继承关系的显式定义:ADMIN(系统管理员)拥有全部权限;DORM_MANAGER(宿管员)继承DORM_STAFF(普通宿管)权限,并额外拥有调宿审批权;COUNSELOR(辅导员)拥有查寝记录查看与导出权,但无任何床位操作权。所有权限标识符(如dorm:bed:assign,repair:order:handle)均采用冒号分隔的命名空间风格,便于前端根据权限列表动态渲染菜单与按钮。

// 在Controller方法上声明权限 @RestController @RequestMapping("/api/bed") public class BedController { @PostMapping("/assign") @PreAuthorize("hasAuthority('dorm:bed:assign')") public Result<String> assignBed(@RequestBody BedAssignRequest request) { // 分配床位业务逻辑 return service.assignBed(request); } @GetMapping("/log/{bedId}") @PreAuthorize("hasAuthority('dorm:bed:log:view')") public Result<List<BedStatusLog>> getBedLog(@PathVariable Long bedId) { // 查询床位状态日志 return service.getBedStatusLog(bedId); } }

注意:权限校验必须放在Controller层,而非Service层。因为Service层应保持纯粹的业务逻辑,不应感知HTTP请求上下文。同时,@PreAuthorize注解的表达式必须简洁,避免在其中编写复杂业务判断(如“只有当学生所在学院为计算机学院时才允许调宿”),这类逻辑应下沉至Service方法内部,由Service抛出特定业务异常(如BusinessException),再由全局异常处理器统一转换为前端友好的错误码。

2.3 关键业务流程:调宿申请与审批的事务一致性保障

调宿是宿舍管理中最易引发数据不一致的场景。学生A申请从301-1调至302-2,系统需原子性完成:1)验证302-2当前为空闲;2)解除A与301-1的关联;3)建立A与302-2的关联;4)生成调宿审批单。若步骤2成功而步骤3失败,将导致A“人房分离”。本方案采用数据库事务+应用层状态机双重保障。所有调宿操作包裹在@Transactional中,确保数据库层面的ACID。更重要的是,在dorm_student关联表中增加status字段(PENDING,APPROVED,REJECTED,CANCELLED),调宿申请初始状态为PENDING,此时学生仍显示为原床位占用者,新床位状态不变;仅当审批通过(APPROVED)时,才触发真正的床位状态变更。这避免了审批过程中的“幽灵床位”问题。

@Service public class DormTransferService { @Transactional public void approveTransfer(Long transferId) { // 1. 查询待审批的调宿申请 DormTransfer transfer = transferMapper.selectById(transferId); if (!"PENDING".equals(transfer.getStatus())) { throw new BusinessException("调宿申请状态非待审批,无法审批"); } // 2. 检查目标床位是否空闲(加行锁,防止并发冲突) DormBed targetBed = bedMapper.selectByIdForUpdate(transfer.getTargetBedId()); if (targetBed.getCurrentStatus() != BedStatus.VACANT.getCode()) { throw new BusinessException("目标床位当前不可用"); } // 3. 更新调宿申请状态为APPROVED transfer.setStatus("APPROVED"); transferMapper.updateById(transfer); // 4. 执行实际的床位分配(更新学生关联、床位状态) studentMapper.updateBedId(transfer.getStudentId(), transfer.getTargetBedId()); bedMapper.updateStatus(transfer.getTargetBedId(), BedStatus.OCCUPIED.getCode()); // 5. 记录状态变更日志 bedStatusLogService.log(transfer.getTargetBedId(), BedStatus.VACANT.getCode(), BedStatus.OCCUPIED.getCode(), transfer.getApproverId(), "调宿审批通过"); } }

提示:selectByIdForUpdate()是MySQL InnoDB的行级锁,能有效防止两个管理员同时审批同一调宿申请导致的超卖。但切记,此锁仅在事务内有效,且必须确保transferMapper.updateById()和后续的bedMapper.updateStatus()在同一事务中执行,否则锁会提前释放。这是学生最容易忽略的“玄学”坑点。

3. 核心模块实现:学生信息与宿舍资源的双向联动

学生信息与宿舍资源并非孤立存在,二者通过入住关系紧密耦合。本模块的实现难点在于如何保证“学生-床位”关系的实时性与准确性,尤其是在批量导入、批量调宿、紧急退宿等场景下。我们摒弃了简单的外键约束(因其无法表达“学生A当前入住301-1,但历史记录中曾入住202-3”这类多版本关系),转而采用主从表+状态标记的设计。dorm_student表作为主表,记录学生当前有效的入住关系;dorm_student_history表作为从表,记录每一次入住、调宿、退宿的完整轨迹。所有对学生入住状态的查询,均以dorm_student表为准;所有审计、统计分析,则查询dorm_student_history表。

3.1 学生信息管理:批量导入的健壮性设计

高校新生入学常需批量导入数千条学生数据,Excel文件格式千奇百怪。本方案的导入功能不依赖第三方Excel解析库(如Apache POI的XSSFWorkbook),而是采用EasyExcel,因其内存占用低、对空行/合并单元格/日期格式异常的容错性极强。导入流程分为三步:1)模板校验(检查列名、必填项、学号唯一性);2)数据解析与转换(将Excel单元格值映射为Java对象,自动处理日期、数字格式);3)数据库批量插入(使用MyBatis-Plus的saveBatch,并开启rewriteBatchStatements=trueJDBC参数提升性能)。最关键的是错误回滚与明细反馈:若某一行数据校验失败(如学号重复、学院代码不存在),整批导入不中断,而是将错误行号、错误原因、原始数据记录到import_error_log表中,最终返回给前端一个包含成功数、失败数及详细错误列表的JSON。

// Excel导入核心逻辑(简化) @PostMapping("/import") public Result<ImportResult> importStudents(@RequestParam("file") MultipartFile file) { ImportResult result = new ImportResult(); List<StudentImportDTO> dataList = new ArrayList<>(); List<ImportError> errorList = new ArrayList<>(); try { // 使用EasyExcel读取,自定义监听器处理每一行 EasyExcel.read(file.getInputStream(), StudentImportDTO.class, new StudentImportListener(dataList, errorList)).sheet().doRead(); // 1. 模板校验:检查学号唯一性、学院是否存在 validateImportData(dataList, errorList); // 2. 数据转换:将DTO转为Entity,并设置默认状态 List<DormStudent> entities = dataList.stream() .map(dto -> { DormStudent entity = new DormStudent(); entity.setStudentId(dto.getStudentId()); entity.setBedId(dto.getBedId()); // 床位ID需先查询 entity.setStatus("ACTIVE"); // 当前状态为激活 return entity; }) .collect(Collectors.toList()); // 3. 批量保存,捕获异常 boolean saved = dormStudentService.saveBatch(entities); result.setSuccessCount(saved ? entities.size() : 0); result.setErrorList(errorList); } catch (Exception e) { log.error("学生批量导入失败", e); result.setErrorList(Collections.singletonList( new ImportError(0, "系统异常", e.getMessage()))); } return Result.success(result); }

注意:validateImportData方法中,对“学号唯一性”的校验不能仅靠内存List遍历,必须调用studentMapper.selectByStudentId()查询数据库,因为可能已有历史数据。但为避免N+1查询,应先将所有待导入学号收集为List,再一次性selectByIds查询,大幅提升性能。

3.2 宿舍资源管理:楼栋-房间-床位的树形结构与容量计算

宿舍资源是静态配置,但其“可用容量”是动态的。一个6人间,若2人已退宿、1人休学,则当前可用床位为3。本方案将楼栋、房间、床位建模为树形结构,dorm_building为根节点,dorm_room为中间节点,dorm_bed为叶子节点。每个节点均存储total_capacity(总容量)与available_count(当前可用数)字段。关键在于available_count的维护策略:它不通过定时任务计算,而是在每一次影响床位状态的操作后,由业务代码主动更新。例如,学生入住时,dorm_bed.current_status变为OCCUPIED,同时触发dorm_room.available_count减1;学生退宿时,dorm_bed.current_status变回VACANT,dorm_room.available_count加1。这种“事件驱动”的更新方式,保证了容量数据的实时性与强一致性。

-- dorm_room 表(关键字段) CREATE TABLE `dorm_room` ( `id` BIGINT PRIMARY KEY AUTO_INCREMENT, `building_id` BIGINT NOT NULL COMMENT '所属楼栋ID', `room_number` VARCHAR(20) NOT NULL COMMENT '房间号,如301, 402A', `total_capacity` INT NOT NULL DEFAULT 4 COMMENT '总床位数', `available_count` INT NOT NULL DEFAULT 4 COMMENT '当前可用床位数', `floor` INT NOT NULL COMMENT '所在楼层', INDEX `idx_building_floor` (`building_id`, `floor`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

提示:dorm_room.available_count字段的更新必须与dorm_bed状态变更在同一个数据库事务中完成。常见错误是:先更新dorm_bed,再异步发送MQ消息去更新dorm_room,这会导致短暂的数据不一致。本方案坚持“同库同事务”,牺牲一点吞吐量,换取绝对的数据准确。

3.3 查寝记录模块:轻量级定时任务与离线数据同步

查寝是宿舍管理的刚需,但要求不高频(通常每日1-2次),且允许一定延迟(如凌晨1点查寝,数据在上午9点前同步即可)。因此,我们未采用WebSocket或长连接推送,而是设计了一个轻量级的定时任务+离线数据包机制。宿管员在移动端APP点击“开始查寝”后,APP本地生成一个包含查寝时间、楼栋、房间、学生ID、状态(在/不在/请假)的JSON数据包,并加密上传至服务器。服务端接收到后,将其存入dorm_checkin_temp临时表,并触发一个Quartz定时任务(每天凌晨2点执行),将临时表中所有数据批量清洗、去重、关联学生信息后,写入正式的dorm_checkin_record表。这种方式极大降低了服务端实时压力,且APP在网络不佳时可缓存数据包,待网络恢复后重传。

// 查寝数据接收Controller @PostMapping("/checkin/upload") public Result<String> uploadCheckinData(@RequestBody CheckinUploadRequest request) { // 1. 解密数据包 String decryptedJson = AesUtil.decrypt(request.getData(), AES_KEY); // 2. 解析为List<CheckinRecord> List<CheckinRecord> records = JSON.parseArray(decryptedJson, CheckinRecord.class); // 3. 批量保存到临时表 checkinTempMapper.insertBatch(records); return Result.success("上传成功"); } // 定时任务:每日凌晨2点执行 @Scheduled(cron = "0 0 2 * * ?") public void syncCheckinRecords() { // 1. 从临时表查询昨日数据 List<CheckinRecord> tempRecords = checkinTempMapper.selectByDate( DateUtil.beginOfDay(DateUtil.offsetDay(new Date(), -1)) ); // 2. 清洗:去重(同一学生同一天多次查寝取最后一次)、补全信息(关联学生姓名、学院) List<CheckinRecord> cleanedRecords = cleanAndEnrich(tempRecords); // 3. 批量插入正式表 checkinRecordMapper.insertBatch(cleanedRecords); // 4. 清空临时表 checkinTempMapper.deleteByDate(...); }

注意:cleanAndEnrich方法中,“去重”逻辑必须使用student_id + checkin_date作为唯一键,而非单纯student_id,否则会丢失同一学生在不同日期的查寝记录。这是学生在实现查寝模块时最常踩的“翻车”点。

4. 常见问题排查:五个让90%开发者深夜崩溃的致命陷阱

在多个高校宿舍管理系统的落地实践中,以下五个问题是导致项目延期、答辩被否、线上故障的最高发区域。它们往往不体现在需求文档里,却在真实运行中暴露得淋漓尽致。请务必在编码前、测试中、上线前,逐条对照自查。

4.1 现象:调宿审批通过后,学生信息页面显示“未分配床位”,但数据库dorm_student表中bed_id字段已正确更新

原因:前端Vue组件在调用approveTransfer接口后,未主动触发getStudentDetail接口刷新学生详情,而是错误地认为“审批成功=数据已更新”,直接修改了本地Vue data中的bedInfo对象。由于dorm_student表与dorm_bed表是分开查询的,前端未重新拉取床位信息,导致视图与数据不一致。
解决:强制约定所有涉及数据变更的API,其成功回调中必须调用对应的refresh方法。例如,审批成功后,必须调用this.fetchStudentDetail(this.studentId),而不是this.student.bedId = this.newBedId。在Axios拦截器中添加日志,监控所有POST /api/transfer/approve的成功响应,确保其后必有GET /api/student/{id}请求。

4.2 现象:维修报修单状态从“已提交”变为“已受理”后,学生端APP收不到推送通知

原因:推送服务(如极光JPush)的设备Token是学生首次登录APP时上报的,但学生更换手机或重装APP后,旧Token失效。系统在更新报修单状态时,仅向jpush_token字段存储的旧Token发送消息,导致推送失败。
解决:在学生登录接口中,增加device_token参数,并在user表中维护latest_device_token字段。每次发送推送前,先查询user.latest_device_token,而非从报修单关联的旧记录中获取。同时,在APP端实现Token自动刷新机制:每次APP启动或网络恢复时,调用/api/user/refresh-token接口更新服务端Token。

4.3 现象:批量导入学生数据时,MySQL报错Packet for query is too large

原因:EasyExcel解析出的List<StudentImportDTO>过大(如1万条),在saveBatch时,MyBatis-Plus默认将所有SQL拼成一条巨大的INSERT语句,超出MySQL的max_allowed_packet限制(默认4MB)。
解决:在MyBatis-Plus的application.yml中配置分批大小:mybatis-plus: batch-size: 1000。同时,在JDBC URL中显式设置?rewriteBatchStatements=true&useServerPrepStmts=true,启用MySQL的预编译批处理优化,将1万条插入拆分为10次1000条的批次,彻底规避包大小限制。

4.4 现象:辅导员在后台导出“本月查寝异常汇总表”,Excel打开后,所有日期列显示为数字(如44562)而非“2022-01-01”

原因:EasyExcel导出时,对Date类型字段未指定@DateTimeFormat注解,导致其默认序列化为自1900年1月1日以来的天数(Excel日期序列)。
解决:在导出用的DTO类中,为所有Date字段添加注解:@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")。若需兼容不同格式,可在@ExcelProperty中指定converter = CustomDateConverter.class,自定义转换逻辑。

4.5 现象:系统运行一周后,bed_status_log表数据量暴增至千万级,getBedLog接口响应时间从200ms飙升至8秒

原因:bed_status_log表缺少针对bed_id和valid_from的联合索引,导致SELECT * FROM bed_status_log WHERE bed_id = ? AND valid_from >= ?查询全表扫描。
解决:立即执行SQL添加索引:ALTER TABLE bed_status_log ADD INDEX idx_bed_valid (bed_id, valid_from);。同时,在application.yml中配置MyBatis-Plus的page-size,强制所有分页查询必须带size参数,禁止SELECT * FROM bed_status_log LIMIT 1000000, 10这类危险SQL。

5. 答辩与验收:用三张表、一个演示脚本、一次压力测试征服评委

答辩不是背诵PPT,而是证明你真的懂、真的做过、真的能跑通。我带过的每一个宿舍管理系统项目,最终都靠一套“看得见、摸得着、测得准”的验收组合拳过关。核心就三点:数据表即证据、演示即流程、压测即底气。下面是我给A同学(某高校毕设)准备的答辩材料包,你可直接复用。

5.1 验收数据表:三张表讲清系统价值

评委最关心“你解决了什么问题”,而不是“你用了什么技术”。用三张精心构造的数据库表截图,比十页PPT更有说服力。

表名关键字段示例说明
dorm_roomid=101, room_number='301', total_capacity=6, available_count=3, floor=3证明资源管理能力:清晰展示301房间总床位6张,当前仅剩3张可用,available_count实时准确,非人工计算。
dorm_student_historyid=5001, student_id='2022001', bed_id=201, status='OCCUPIED', start_date='2023-09-01', end_date='2024-01-15'
id=5002, student_id='2022001', bed_id=202, status='OCCUPIED', start_date='2024-01-16', end_date=NULL
证明业务流程能力:同一学生2022001在301-1住到2024-01-15,1月16日调至302-2(bed_id=202),end_date=NULL表示当前入住。历史轨迹完整,无断点。
repair_orderid=888, student_id='2022002', bed_id=201, status='COMPLETED', handle_time='2024-02-20 14:30:00', completion_time='2024-02-20 16:15:00'证明闭环管理能力:报修单从提交到完成耗时1小时45分钟,completion_time非空,证明维修流程真实走完,非摆设。

提示:答辩时,不要说“我的系统有XX功能”,而是直接打开数据库客户端,指着这三张表说:“请看,这就是系统运行一周后的真实数据。301房间可用床位是3,不是我猜的;学生2022001的调宿记录有始有终;维修单888的完成时间是系统自动记录的。数据不会说谎。”

5.2 演示脚本:五分钟覆盖所有核心场景

评委没耐心看十分钟演示。我帮A同学写了份严格计时的五分钟脚本,确保每个环节都直击要害:

  1. 0:00-0:45 入住登记:用测试账号(学生A)登录,填写基本信息,选择301-1床位,点击“确认入住”。重点展示:提交后,页面立即显示“入住成功”,同时刷新dorm_room.available_count从3变为2(后台数据库实时刷新)。
  2. 0:46-2:00 调宿申请与审批:学生A在个人中心提交调宿申请,目标302-2。切换至宿管员账号,进入“待审批列表”,找到该申请,点击“同意”。重点展示:审批后,学生A的床位信息秒级更新为302-2,且301-1的available_count加1,302-2的available_count减1。
  3. 2:01-3:30 维修报修:学生A在“报修中心”提交一张关于302-2床板松动的报修单。切换至维修工账号,查看“待处理单”,点击“已受理”,填写处理意见并提交。重点展示:学生A端APP收到推送,且报修单状态变为“已完成”,completion_time自动填充。
  4. 3:31-5:00 查寝记录:宿管员在“查寝”模块,选择302房间,勾选学生A为“在”,点击“提交”。重点展示:提交后,dorm_checkin_record表中立即新增一条记录,status为IN,checkin_time为当前精确时间。

注意:所有演示必须使用真实数据库,禁用Mock或内存H2。提前准备好测试账号(学生A、宿管员、维修工)和测试数据(301、302房间),确保每一步操作都在10秒内完成。卡顿就是硬伤。

5.3 压力测试报告:用JMeter证明系统不是玩具

很多同学答辩时被问:“系统能支持多少人同时用?”答“应该可以”是自杀。A同学用JMeter做了两组测试,报告成为答辩最大亮点:

  • 场景1:查寝高峰期:模拟100名宿管员在5分钟内,对全校1000个房间(约6000床位)完成查寝。结果:平均响应时间<800ms,错误率0%,CPU使用率<65%。
  • 场景2:新生报到日:模拟500名学生在1小时内完成入住登记。结果:平均响应时间<1200ms,错误率0%,数据库连接池未打满。
# JMeter测试脚本关键参数(供你参考) # Thread Group: Number of Threads = 100 # Ramp-up Period = 300 seconds (5 minutes) # Loop Count = 1 # HTTP Request Defaults: Server Name = your-server-ip, Port = 8080 # HTTP Header Manager: Content-Type = application/json; charset=UTF-8 # View Results Tree: Disabled (for performance)

从那以后我每次做毕设,答辩前必做三件事:1)用真实数据跑通三张核心表;2)按脚本彩排演示五次,掐表到秒;3)用JMeter跑一遍压力测试,哪怕只跑10个线程,也要有报告。这三件事做完,答辩时心里才有底,不是背稿子,而是讲事实。希望帮到你。

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

返回列表