1. 项目背景与核心需求
学生宿舍管理系统是高校信息化建设中的基础模块,但传统系统普遍存在几个痛点:数据孤岛现象严重、移动端适配不足、审批流程僵化。我们团队在调研了7所高校的实际需求后,决定采用前后端分离架构开发这套系统。
这个系统的核心要解决三个问题:
- 实时掌握1200+床位动态使用情况
- 实现维修、请假等8类业务流程线上化
- 生成16种维度的住宿数据分析报表
技术选型上,后端采用SpringBoot 2.7 + MyBatis-Plus 3.5的组合,前端使用Vue 3 + Element Plus。这个技术栈的选择基于三个考量:首先,SpringBoot的自动配置特性能让团队快速搭建RESTful API;其次,MyBatis-Plus的ActiveRecord模式简化了90%的单表操作;最后,Vue3的组合式API更适合复杂表单交互场景。
2. 系统架构设计
2.1 整体技术架构
系统采用经典的三层架构:
code复制表示层:Vue3 + Axios + Element Plus
业务层:SpringBoot + Spring Security
数据层:MySQL 8.0 + Redis 6.2
前后端通过JWT进行认证,接口文档使用Swagger 3.0自动生成。特别要说明的是,我们在网关层做了接口调用频次限制,防止恶意刷单行为。
2.2 数据库设计要点
宿舍系统的ER图有12个核心实体,这里重点说明几个关键设计:
- 宿舍楼表(dorm_building)采用"软删除"设计,添加is_deleted字段而非物理删除
- 学生住宿记录表(stay_record)包含begin_date和end_date,支持历史记录追溯
- 维修工单表(repair_order)使用status字段配合状态模式实现工单流转
sql复制CREATE TABLE `student` (
`id` bigint NOT NULL AUTO_INCREMENT,
`student_no` varchar(20) NOT NULL COMMENT '学号',
`name` varchar(50) NOT NULL,
`gender` tinyint DEFAULT '0',
`college_id` int NOT NULL COMMENT '学院ID',
`class_id` int NOT NULL COMMENT '班级ID',
`bed_id` bigint DEFAULT NULL COMMENT '床位ID',
PRIMARY KEY (`id`),
UNIQUE KEY `idx_student_no` (`student_no`),
KEY `idx_bed_id` (`bed_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
3. 核心功能实现
3.1 宿舍分配算法实现
分配逻辑考虑三个维度:
- 同专业优先集中原则
- 男女分层隔离原则
- 特殊需求优先原则
核心Java代码片段:
java复制public class DormAllocator {
public List<Bed> autoAllocate(List<Student> students) {
return students.stream()
.sorted(Comparator
.comparing(Student::getGender)
.thenComparing(Student::getMajorCode))
.map(student -> {
Bed bed = bedService.findAvailableBed(
student.getGender(),
student.getMajorCode());
if (bed != null) {
bed.setStudentId(student.getId());
bed.setStatus(BedStatus.OCCUPIED);
}
return bed;
})
.filter(Objects::nonNull)
.collect(Collectors.toList());
}
}
3.2 可视化床位管理
前端使用SVG实现楼层平面图渲染,关键点:
- 使用vue-draggable实现床位拖拽调整
- 通过WebSocket实时同步床位状态变更
- 颜色编码区分空床/维修中/已入住状态
vue复制<template>
<svg :viewBox="`0 0 ${width} ${height}`">
<g v-for="room in rooms" :key="room.id">
<rect :x="room.x" :y="room.y"
width="100" height="80"
:class="`room ${room.status}`"/>
<Bed v-for="bed in room.beds"
:key="bed.id"
:x="bed.x"
:y="bed.y"
:status="bed.status"
@click="handleBedClick(bed)"/>
</g>
</svg>
</template>
4. 典型业务场景实现
4.1 维修工单流程
工单状态机设计:
code复制待受理 -> 已分配 -> 维修中 -> 待验收 -> 已完成
↘ ↖
已驳回 返工
后端使用状态模式封装流转逻辑:
java复制public interface RepairOrderState {
void handle(RepairOrderContext context);
}
@Service
@RequiredArgsConstructor
public class RepairOrderService {
private final Map<String, RepairOrderState> stateHandlers;
public void changeState(Long orderId, String action) {
RepairOrder order = getById(orderId);
stateHandlers.get(order.getStatus())
.handle(new RepairOrderContext(order, action));
}
}
4.2 晚归登记模块
移动端实现要点:
- 使用百度地图API获取定位坐标
- 结合人脸识别进行身份核验
- 自动关联宿舍门禁系统数据
javascript复制const submitLateReturn = async () => {
const position = await getCurrentPosition()
const faceResult = await faceVerify()
if (!faceResult.success) {
throw new Error('人脸验证失败')
}
return axios.post('/api/late-return', {
studentId: userStore.id,
dormId: currentDorm.value,
coordinates: [position.lng, position.lat],
photo: faceResult.photo
})
}
5. 系统部署与优化
5.1 性能优化措施
-
MySQL层面:
- 为高频查询添加复合索引
- 大表使用分库分表(按学年分片)
- 使用Redis缓存热点数据
-
Java层面:
- 启用HikariCP连接池
- 添加二级缓存(Caffeine)
- 异步处理报表生成任务
-
Vue层面:
- 路由懒加载
- 使用keep-alive缓存常用组件
- 按需引入Element Plus组件
5.2 安全防护方案
-
接口安全:
- 所有API添加JWT校验
- 敏感操作要求二次密码确认
- 使用Spring Security的@PreAuthorize注解
-
数据安全:
- 密码使用BCrypt加密存储
- 日志脱敏处理
- 数据库定时备份到OSS
-
防攻击措施:
- 集成Spring Boot Actuator监控异常请求
- 使用Sentinel实现熔断降级
- 关键表单添加CSRF Token
6. 开发中的经验总结
- MyBatis-Plus的Lambda查询比XML更易维护:
java复制// 不推荐
@Select("SELECT * FROM student WHERE college_id = #{collegeId}")
List<Student> findByCollege(Long collegeId);
// 推荐
List<Student> students = studentService.lambdaQuery()
.eq(Student::getCollegeId, collegeId)
.list();
- Vue3组合式API的封装技巧:
javascript复制// 封装useDormHook
export function useDorm() {
const dormList = ref([])
const loadDorms = async (buildingId) => {
dormList.value = await api.getDormsByBuilding(buildingId)
}
return { dormList, loadDorms }
}
// 在组件中使用
const { dormList, loadDorms } = useDorm()
onMounted(() => loadDorms(props.buildingId))
- 跨域问题的终极解决方案:
java复制@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("*")
.allowedHeaders("*")
.exposedHeaders("Authorization")
.maxAge(3600);
}
}
这套系统在部署后,日均处理300+条业务请求,高峰期并发达到50QPS。最大的收获是深入理解了如何在前端复杂表单交互和后端高并发写入之间找到平衡点。特别是在宿舍分配算法优化上,我们迭代了4个版本才达到秒级响应的目标。
