1. 项目概述
作为一名经历过多次毕业设计指导的开发者,我想分享一个基于Java技术栈的高校疫情防疫管理系统开发经验。这个系统最初源于某高校的实际需求,旨在解决校园防疫管理中的痛点问题:纸质健康打卡效率低下、人工统计易出错、隔离信息更新不及时等。
在开发过程中,我们团队踩过不少坑,也积累了许多宝贵经验。比如初期设计时,我们忽略了检测信息表与用户表的外键关联,导致后期数据查询效率极低,不得不花费大量时间重构数据库结构。这些教训让我深刻认识到,一个优秀的毕业设计不仅要有完整功能,更要有合理的架构设计。
2. 需求分析与设计
2.1 核心功能定位
在需求分析阶段,我们首先明确了系统的两大核心用户角色:
- 管理员:负责用户管理、健康数据监控、隔离区域管理、物资调配等
- 普通用户(师生):进行日常健康打卡、出行申报、信息查询等
经过多次需求讨论,我们确定了以下核心功能模块:
- 健康监测管理:包括每日健康打卡、异常体温预警
- 出行申报审批:师生出行申请及审核流程
- 隔离区域管理:风险区域标记与信息维护
- 防疫物资管理:库存监控与调配
- 信息发布:公告与疫情动态推送
2.2 数据库设计要点
数据库设计是系统的基础,我们采用了MySQL 5.7作为数据库,主要考虑了以下几点:
-
表关系设计:
- 用户表(yonghu)与检测信息表(daka)建立一对多关系
- 物资表(wuzi)与物资收藏表(wuzi_collection)建立一对多关系
- 使用外键约束确保数据完整性
-
字段设计规范:
- 所有表都包含create_time和update_time字段
- 状态字段使用types后缀(如daka_types)
- 实现逻辑删除机制(delete_flag字段)
-
性能优化:
- 为常用查询字段添加索引
- 大文件(如图片)只存储路径而非二进制数据
- 使用utf8mb4字符集支持完整Unicode
3. 技术实现细节
3.1 后端架构设计
我们采用Spring Boot 2.5.x作为后端框架,主要模块包括:
- 核心依赖:
xml复制<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.8</version>
</dependency>
- 分层架构:
- Controller层:处理HTTP请求
- Service层:业务逻辑实现
- DAO层:数据库操作
- Model层:数据实体
- 关键功能实现:
- 使用Spring Security实现权限控制
- 配置Druid数据源监控
- 实现全局异常处理
- 添加日志记录(Log4j2)
3.2 前端实现方案
前端采用Vue 2.x + ElementUI组合,主要特点:
- 页面结构:
- 管理员端:采用侧边栏导航布局
- 用户端:采用顶部导航+内容区布局
- 核心组件:
- 健康打卡表单:包含健康码状态选择、体温输入、图片上传
- 数据表格:支持分页、筛选、排序
- 图表展示:使用ECharts实现数据可视化
- 交互优化:
- 表单实时验证
- 操作结果Toast提示
- 加载状态指示器
4. 开发中的关键问题与解决方案
4.1 健康打卡唯一性校验
初期版本允许用户同一天多次打卡,导致数据混乱。解决方案:
- 数据库层面:添加唯一索引(user_id + date)
- 业务逻辑层:先查询当日是否已打卡
- 前端提示:友好提醒"今日已打卡"
实现代码示例:
java复制@Transactional
public Result addDaka(DakaEntity daka) {
// 检查当日是否已打卡
LambdaQueryWrapper<DakaEntity> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(DakaEntity::getYonghuId, daka.getYonghuId())
.ge(DakaEntity::getCreateTime, LocalDate.now().atStartOfDay())
.le(DakaEntity::getCreateTime, LocalDate.now().atTime(23, 59, 59));
if(dakaService.count(queryWrapper) > 0) {
return Result.error("今日已打卡,请勿重复提交");
}
// 保存打卡记录
dakaService.save(daka);
return Result.ok("打卡成功");
}
4.2 物资库存并发控制
多管理员同时操作物资库存时可能出现超卖问题。解决方案:
- 使用数据库乐观锁:
java复制@Transactional
public Result updateStock(Long id, Integer changeAmount) {
WuziEntity wuzi = wuziService.getById(id);
if(wuzi == null) {
return Result.error("物资不存在");
}
int newStock = wuzi.getWuziKucunNumber() + changeAmount;
if(newStock < 0) {
return Result.error("库存不足");
}
wuzi.setWuziKucunNumber(newStock);
wuziService.updateById(wuzi);
// 记录库存变更日志
WuziLogEntity log = new WuziLogEntity();
log.setWuziId(id);
log.setChangeAmount(changeAmount);
log.setRemarks("库存调整");
wuziLogService.save(log);
return Result.ok("操作成功");
}
- 添加库存操作日志表
- 前端添加操作确认提示
5. 系统测试与优化
5.1 测试策略
我们采用分层测试策略:
- 单元测试:使用JUnit测试Service层方法
- 接口测试:使用Postman测试API接口
- 集成测试:模拟用户完整操作流程
- 性能测试:使用JMeter模拟并发请求
5.2 性能优化措施
- 数据库优化:
- 添加适当索引
- 优化复杂查询SQL
- 使用连接池(Druid)
- 缓存策略:
- 缓存字典数据
- 缓存热点查询结果
- 前端优化:
- 组件懒加载
- 路由按需加载
- 图片压缩
6. 项目部署方案
6.1 环境要求
- JDK 1.8
- MySQL 5.7
- Tomcat 8.5
- Node.js (前端构建)
6.2 部署步骤
- 数据库部署:
sql复制CREATE DATABASE campus_epidemic_system CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
- 后端部署:
- 打包Spring Boot应用:
mvn clean package - 将war包部署到Tomcat
- 前端部署:
- 构建生产版本:
npm run build - 将dist目录内容部署到Nginx
7. 毕业设计答辩建议
基于多次指导经验,我总结出以下答辩技巧:
- 演示重点:
- 展示核心业务流程(打卡→审核→统计)
- 突出技术难点解决方案
- 演示系统响应速度
- 问题准备:
- 准备系统设计思路的解释
- 准备性能优化措施的说明
- 准备扩展性方面的考虑
- 文档整理:
- 提供清晰的系统架构图
- 准备数据库ER图
- 整理测试用例和结果
在实际开发过程中,我们最大的体会是:不要过度追求技术新颖性,而应该把精力放在系统的稳定性和用户体验上。比如我们最初考虑使用Redis缓存,但考虑到系统规模和学习成本,最终选择了更简单的方案,这反而让项目更容易维护和扩展。