1. 项目背景与核心价值
校园疫情管理是当前教育机构面临的重要课题。去年在某高校信息化部门工作时,我们团队就深刻体会到传统纸质登记+Excel统计方式的低效——每天要处理近万条健康打卡数据,人工核对缺勤学生信息常常需要3-4小时。这正是我们决定开发这套微信小程序管理系统的初衷。
选择SpringBoot+微信小程序的方案,主要基于三个实际考量:
- 微信生态覆盖了95%以上的在校师生,无需额外安装APP
- SpringBoot的自动配置特性可以快速搭建RESTful API服务
- 两者结合能实现7*24小时的实时疫情监控能力
2. 技术架构设计
2.1 整体技术栈选型
采用经典的三层架构:
- 前端:微信小程序 + Vant Weapp组件库
- 后端:SpringBoot 2.7 + MyBatis-Plus
- 数据库:MySQL 8.0(需特别注意5.7与8.0的JSON字段差异)
graph TD A[微信小程序] --> B[SpringBoot API] B --> C[MySQL] C --> D[Redis缓存] D --> E[阿里云OSS]2.2 数据库关键表设计
核心表结构经过三次迭代优化:
CREATE TABLE `health_report` ( `id` bigint NOT NULL AUTO_INCREMENT, `student_id` varchar(20) NOT NULL COMMENT '学号', `temperature` decimal(3,1) NOT NULL COMMENT '体温', `health_status` tinyint NOT NULL COMMENT '0正常 1发热 2咳嗽...', `location` json DEFAULT NULL COMMENT 'GPS定位数据', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `idx_date_student` (`student_id`,`create_time`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;3. 核心功能实现
3.1 微信小程序端关键技术
- 定位防作弊机制:
wx.getLocation({ type: 'gcj02', success: (res) => { // 对比学校地理围栏坐标 if(!checkInSchool(res.latitude, res.longitude)){ wx.showToast({ title: '请在校内打卡', icon: 'error' }) } } })- Canvas动态健康码: 通过小程序canvas API生成包含实时时间的动态健康码,防止截图冒用:
const ctx = wx.createCanvasContext('healthCode') ctx.setFillStyle('#27ae60') ctx.fillRect(0, 0, 300, 150) ctx.setFontSize(14) ctx.fillText(new Date().toLocaleString(), 20, 80) ctx.draw()3.2 SpringBoot后端关键代码
- 定时统计模块:
@Scheduled(cron = "0 0 23 * * ?") public void dailyReport() { // 使用MyBatis-Plus的Lambda查询 List<HealthReport> reports = lambdaQuery() .ge(HealthReport::getCreateTime, LocalDateTime.now().withHour(0)) .list(); // 生成统计报表并发送邮件 EmailUtil.sendDailyReport(statisticService.generateReport(reports)); }- 异常预警接口:
@PostMapping("/alert") public Result<?> alertHandler(@RequestBody AlertDTO dto) { // 使用Redis实现每分钟限流 String key = "alert:" + dto.getStudentId(); if (redisTemplate.opsForValue().increment(key) > 3) { throw new BusinessException("操作过于频繁"); } redisTemplate.expire(key, 1, TimeUnit.MINUTES); // 处理预警逻辑 warningService.processAlert(dto); return Result.success(); }4. 部署与性能优化
4.1 生产环境配置
采用Docker Compose部署方案:
version: '3' services: mysql: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: ${DB_PASSWORD} volumes: - ./mysql/data:/var/lib/mysql - ./mysql/conf:/etc/mysql/conf.d redis: image: redis:6-alpine command: redis-server --requirepass ${REDIS_PASSWORD} app: build: . ports: - "8080:8080" depends_on: - mysql - redis4.2 高并发应对策略
通过JMeter压力测试发现两个性能瓶颈:
- 健康码生成接口QPS仅150
- 批量查询接口响应时间超过2s
优化方案:
- 引入Guava缓存健康码模板
- 对MySQL添加复合索引:
ALTER TABLE health_report ADD INDEX idx_status_time (health_status, create_time);5. 典型问题解决方案
5.1 微信小程序审核驳回
常见原因及对策:
定位权限说明不清晰: 在app.json中补充完整用途说明:
"permission": { "scope.userLocation": { "desc": "用于验证您是否在校内进行健康打卡" } }表单内容违规: 避免收集身份证号等敏感信息,改用学号+密码验证
5.2 数据库连接池耗尽
现象:凌晨定时任务运行时出现"HikariPool-1 - Connection is not available"错误
解决方案:
- 调整连接池配置:
spring.datasource.hikari.maximum-pool-size=20 spring.datasource.hikari.idle-timeout=30000- 优化批量查询SQL,添加LIMIT分页
6. 项目扩展方向
物联网集成: 通过蓝牙对接体温枪设备,实现自动测温上报
可视化大屏: 使用ECharts实现校区热力图展示
智能预警: 基于历史数据建立预测模型,提前发现潜在风险
关键经验:在正式上线前,务必用真实数据做全流程测试。我们曾遇到MySQL的GROUP BY查询在测试环境(100条数据)很快,但生产环境(10万+数据)超时的情况,最后通过添加覆盖索引解决。