1. 项目背景与核心价值
校园健康驿站管理系统是当前高校信息化建设中的重要一环。随着高校规模的扩大和学生健康管理需求的提升,传统纸质登记和分散管理的方式已经无法满足实际需求。这套基于SpringBoot+Vue的技术方案,正是为了解决以下痛点:
- 健康数据孤岛问题:学生体检数据、日常健康申报、门诊记录分散在不同系统中
- 实时性不足:疫情等突发公共卫生事件下的快速响应能力欠缺
- 管理效率低下:人工统计耗时耗力,且容易出错
- 移动端支持薄弱:学生和教职工需要更便捷的健康服务入口
我在实际部署中发现,这套系统通过三个技术层级的配合实现了突破:
- SpringBoot后端提供稳定的RESTful API(实测QPS可达1200+)
- Vue前端实现动态数据展示和用户友好交互
- MyBatis+MySQL保证数据持久化的可靠性和查询效率
关键提示:系统采用JWT+RBAC实现细粒度权限控制,管理员、校医、辅导员、学生等不同角色看到的界面和功能完全不同
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术架构详解
2.1 SpringBoot后端设计
核心模块采用Maven多模块架构:
code复制health-parent
├── health-common // 公共组件
├── health-system // 系统管理
├── health-clinic // 门诊管理
└── health-mobile // 移动端接口
特色配置项:
yaml复制# application-prod.yml
spring:
datasource:
druid:
filters: stat,wall,log4j
max-active: 50
initial-size: 5
redis:
lettuce:
pool:
max-active: 16
避坑经验:在测试环境遇到过Redis连接泄漏问题,最终通过lettuce的shutdown-timeout配置解决
2.2 Vue前端工程化实践
前端采用Vue CLI 4.x搭建,关键依赖:
json复制{
"dependencies": {
"vue": "^2.6.11",
"vue-router": "^3.2.0",
"axios": "^0.21.1",
"element-ui": "^2.15.1",
"echarts": "^5.1.2"
}
}
路由守卫的典型实现:
javascript复制router.beforeEach((to, from, next) => {
if (to.meta.requiresAuth && !store.getters.token) {
next('/login?redirect=' + encodeURIComponent(to.fullPath))
} else {
next()
}
})
2.3 MyBatis优化技巧
针对健康数据查询特点,我们做了以下优化:
- 二级缓存配置(注意医疗数据的时效性要求)
xml复制<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
- 动态SQL处理复杂查询条件
xml复制<select id="selectHealthRecords" resultMap="BaseResultMap">
SELECT * FROM t_health_record
<where>
<if test="studentId != null">AND student_id = #{studentId}</if>
<if test="startDate != null">AND create_time >= #{startDate}</if>
<choose>
<when test="type == 1">AND temperature > 37.3</when>
<otherwise>AND temperature <= 37.3</otherwise>
</choose>
</where>
ORDER BY create_time DESC
</select>
3. 数据库设计与优化
3.1 核心表结构
sql复制CREATE TABLE `t_student_health` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`student_id` varchar(20) NOT NULL COMMENT '学号',
`temperature` decimal(3,1) DEFAULT NULL COMMENT '体温',
`symptoms` varchar(255) DEFAULT NULL COMMENT '症状',
`contact_history` tinyint(1) DEFAULT '0' COMMENT '接触史',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_student` (`student_id`),
KEY `idx_time` (`create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
3.2 性能优化实践
- 针对分页查询的优化方案:
java复制// 使用MyBatis-Plus的分页插件
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
- 大数据量导出时的处理技巧:
java复制// 使用流式查询避免OOM
@Select("SELECT * FROM t_health_record WHERE create_time >= #{startDate}")
@Options(resultSetType = ResultSetType.FORWARD_ONLY, fetchSize = 1000)
@ResultMap("BaseResultMap")
void exportHealthData(Date startDate, ResultHandler<HealthRecord> handler);
4. 典型业务场景实现
4.1 健康打卡流程
时序图关键节点:
- 学生微信端提交表单
- 服务端校验数据完整性
- 异常数据触发告警规则
- 辅导员后台查看未打卡名单
核心校验逻辑:
java复制public void validateHealthReport(HealthReportDTO dto) {
if (dto.getTemperature() == null) {
throw new BizException("体温数据不能为空");
}
if (dto.getTemperature().compareTo(new BigDecimal("45")) > 0) {
throw new BizException("体温数据异常");
}
// 更多业务规则校验...
}
4.2 疫情预警机制
基于规则引擎的实现:
java复制// 规则配置表
CREATE TABLE `t_alert_rule` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`rule_name` varchar(50) NOT NULL,
`condition_expression` varchar(500) NOT NULL,
`alert_level` tinyint(4) NOT NULL,
PRIMARY KEY (`id`)
);
// 规则引擎处理
public List<Alert> checkRules(HealthRecord record) {
List<AlertRule> rules = ruleMapper.selectAll();
return rules.stream()
.filter(rule -> evalExpression(rule.getConditionExpression(), record))
.map(rule -> new Alert(record.getStudentId(), rule.getAlertLevel()))
.collect(Collectors.toList());
}
5. 部署与运维实践
5.1 生产环境部署方案
推荐架构:
code复制Nginx(负载均衡)
├── SpringBoot应用节点1
├── SpringBoot应用节点2
└── SpringBoot应用节点3
↑
MySQL主从集群(1主2从)
↑
Redis哨兵集群
关键启动参数:
bash复制java -jar health-system.jar \
--spring.profiles.active=prod \
--server.tomcat.max-threads=200 \
--spring.datasource.hikari.maximum-pool-size=20
5.2 常见问题排查
-
微信回调地址配置问题:
- 检查Nginx的
proxy_set_header Host $host;配置 - 验证微信公众平台的白名单IP设置
- 检查Nginx的
-
定时任务不执行:
- 检查
@EnableScheduling注解是否启用 - 确认Quartz表结构是否初始化
- 检查
-
导出Excel内存溢出:
- 使用POI的SXSSFWorkbook模式
- 增加JVM参数:
-XX:+UseG1GC -Xmx1024m
6. 扩展与二次开发
6.1 与现有系统集成
- 统一认证对接示例:
java复制public class SsoFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain chain) {
String token = request.getHeader("X-Auth-Token");
AuthUser user = ssoClient.validateToken(token);
SecurityContextHolder.getContext().setAuthentication(
new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities()));
chain.doFilter(request, response);
}
}
- 数据同步方案比较:
- 方案1:MySQL主从复制(实时性高)
- 方案2:Kafka消息队列(解耦性好)
- 方案3:定时任务+API调用(实现简单)
6.2 移动端优化技巧
- 图片压缩策略:
java复制public String compressImage(MultipartFile file) {
Thumbnails.of(file.getInputStream())
.scale(0.5f)
.outputQuality(0.7f)
.toFile(new File("/tmp/compressed.jpg"));
return uploadToOSS("/tmp/compressed.jpg");
}
- 离线模式处理:
javascript复制// Vue中检测网络状态
window.addEventListener('online', this.syncLocalData);
window.addEventListener('offline', () => {
this.$message.warning('网络断开,已启用离线模式');
});
这套系统在我们学校实际运行一年来,日均处理健康申报3000+条,高峰期并发达到200+QPS。最大的收获是:一定要在开发初期就建立完善的日志监控体系,我们后来通过ELK收集业务日志,排查效率提升了70%以上。对于需要二次开发的同行,建议先仔细阅读模块间的依赖关系文档,避免修改一个功能引发连锁问题。
