1. 项目背景与需求分析
在大学校园信息化建设中,教室资源的高效管理一直是个痛点。传统的人工登记方式存在信息滞后、冲突频发、统计困难等问题。我去年为某高校开发的这套系统,上线后教室使用率提升了35%,管理人力成本降低了60%。
核心需求来自三个维度:
- 学生端:需要实时查看教室空闲状态,支持多条件筛选(如容量、设备类型),能快速完成预约/取消操作
- 教师端:需优先预约权限,支持长期固定预约(如每周三1-2节),能查看历史使用记录
- 管理端:需要可视化监控各教室实时状态,生成多维度的使用报表,具备冲突自动检测功能
关键点:系统设计必须考虑高校特有的教学作息(如两节课间10分钟过渡期),预约粒度建议设置为45分钟(半节课)为单位,既保证灵活性又避免碎片化。
2. 技术架构设计
2.1 整体架构方案
采用经典的三层架构,但针对教室预约场景做了特殊优化:
前端:Vue3 + Element Plus(兼容移动端) 网关:Spring Cloud Gateway 业务层:SpringBoot 2.7 + MyBatis-Plus 数据层:MySQL 8.0(主从分离) + Redis(缓存课表) 定时任务:XXL-JOB 消息队列:RocketMQ(处理预约冲突通知)2.2 数据库设计要点
核心表关系如图所示(此处应有ER图,文字描述替代):
- classroom:记录教室基础信息(位置、容量、设备等),设置is_active控制可用状态
- timeslot:存储全校统一的时间段定义(如1-2节对应08:00-09:35)
- reservation:包含start_time/end_time、status(0待审核1已预约2已取消)等字段
- 特别注意:建立联合索引(classroom_id, date, timeslot_id)提升查询效率
踩坑记录:初期未考虑学期切换场景,导致历史数据查询异常。后增加academic_year字段,并采用分表策略(按学年拆分reservation表)
3. 核心功能实现
3.1 预约冲突检测算法
这是系统最复杂的业务逻辑,采用多级校验策略:
// 伪代码示例 public boolean checkConflict(ReservationDTO dto) { // 1. 基础校验(时间有效性、教室是否存在) validateBasic(dto); // 2. 查缓存获取该教室当天所有预约记录 List<Reservation> existList = getFromRedis(dto.getClassroomId(), dto.getDate()); // 3. 时间段重叠检测(考虑不同预约粒度) return existList.stream().noneMatch(r -> !r.getStatus().equals(CANCELED) && isTimeOverlap(r.getTimeslot(), dto.getTimeslot())); } // 使用Joda-Time处理复杂时间计算 private boolean isTimeOverlap(TimeSlot s1, TimeSlot s2) { return new Interval(s1.getStart(), s1.getEnd()) .overlaps(new Interval(s2.getStart(), s2.getEnd())); }3.2 动态权限控制
基于Spring Security的扩展实现:
- 学生:最大连续预约2小时,每天上限4小时
- 教师:可预约整天的教室(需审核)
- 管理员:拥有强制取消权限,操作记录留痕
@PreAuthorize("@rbacService.checkAccess(#classroomId, 'BOOK')") @PostMapping("/reserve") public Result reserve(@RequestBody ReservationDTO dto) { // 业务逻辑 }4. 性能优化实践
4.1 缓存策略设计
采用多级缓存解决高并发查询:
- 第一层:Redis缓存未来7天教室状态(bitmap存储)
- 第二层:Caffeine本地缓存教室基础信息
- 特殊处理:期末考试周前预热缓存
4.2 数据库优化
- 索引优化:为reservation表添加复合索引(user_id, status)
- 查询优化:使用MyBatis-Plus的QueryWrapper避免N+1问题
- 连接池:配置HikariCP参数(maxPoolSize=50, idleTimeout=3min)
5. 部署与监控
5.1 容器化部署
Docker Compose编排方案:
services: app: image: classroom-booking:1.0 depends_on: - redis - mysql environment: - SPRING_PROFILES_ACTIVE=prod deploy: resources: limits: cpus: '2' memory: 2G5.2 监控体系
- Prometheus采集JVM指标
- Grafana展示教室使用热力图
- 关键业务指标埋点(预约成功率、冲突率等)
6. 踩坑与经验
- 时间处理坑:必须统一使用UTC时间存储,前端按时区转换。曾因夏令时导致预约错乱
- 并发问题:使用@DistributedLock注解防止超卖,底层基于Redis实现
- 微信通知延迟:改用RocketMQ的延迟消息功能(等级3对应10秒延迟)
项目源码中特别值得参考的部分:
- 预约状态机设计(使用State Pattern)
- 自定义注解@OperationLog实现审计功能
- 基于策略模式的冲突检测算法扩展