1. 项目概述与背景
SpringBoot 1.10养老年人问诊服务预约系统是我在医疗信息化领域的一次实践探索。随着老龄化社会加速到来,老年人就医难问题日益凸显——不熟悉智能手机操作、线下排队体力不支、子女陪同时间有限等痛点亟待解决。这个系统正是针对这些实际问题设计的解决方案。
系统采用B/S架构,基于SpringBoot 1.10框架开发,整合了医疗预约、健康监测、医患沟通等核心功能。我在开发过程中特别注重适老化设计:界面采用1.5倍标准字体大小,关键操作按钮不小于44×44像素的触控区域,所有功能入口都配有语音引导。这些细节来自我实地走访养老院时收集的真实需求。
2. 技术架构解析
2.1 后端技术选型
选择SpringBoot 1.10而非最新版本是经过慎重考虑的。这个长期支持版本(LTS)具有更好的稳定性,且与医院现有HIS系统对接时兼容性更佳。核心技术栈包括:
- 持久层:MyBatis-Plus 3.4.3(简化CRUD操作)
- 安全框架:Spring Security 5.3.9(实现RBAC权限控制)
- 缓存机制:Redis 6.x(缓解挂号高峰期的并发压力)
- API文档:Swagger2.9.2(方便前端对接)
数据库设计上,我采用MySQL 8.0的JSON类型字段存储动态健康数据(如血压记录),这样既保持关系型数据库的优势,又满足半结构化数据存储需求。以下是核心表结构示例:
sql复制CREATE TABLE `elderly_user` (
`id` bigint NOT NULL AUTO_INCREMENT,
`id_card` varchar(18) COLLATE utf8mb4_bin NOT NULL COMMENT '身份证号',
`family_contacts` json DEFAULT NULL COMMENT '紧急联系人[{name,phone,relation}]',
`health_profile` json DEFAULT NULL COMMENT '健康档案',
PRIMARY KEY (`id`),
UNIQUE KEY `idx_idcard` (`id_card`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
2.2 前端适配方案
考虑到老年用户群体特性,系统提供三种前端方案:
- Web端:采用Thymeleaf + Bootstrap 4.6(兼容IE11)
- 微信小程序:使用WXML + WXSS(子女可代为操作)
- 医院自助终端:Electron封装的触屏优化版本
特别开发了"极简模式",通过?simple=true参数可切换至仅保留核心功能的界面,去除所有非必要元素,降低认知负荷。
3. 核心功能实现
3.1 智能预约调度算法
挂号模块不是简单的CRUD,而是包含复杂的业务规则:
java复制// 预约规则校验器
public class AppointmentValidator {
// 检查同一医生同时间段是否重复预约
public boolean checkDuplicate(AppointmentDTO dto) {
return appointmentMapper.selectCount(new QueryWrapper<Appointment>()
.eq("doctor_id", dto.getDoctorId())
.eq("time_slot", dto.getTimeSlot())
.eq("appoint_date", dto.getAppointDate())) == 0;
}
// 老年人专属时段检查(上午9-11点保留30%号源)
public boolean isElderlyPreferredTime(LocalTime time) {
return time.isAfter(LocalTime.of(9,0))
&& time.isBefore(LocalTime.of(11,0));
}
}
3.2 健康数据异常预警
对接蓝牙医疗设备采集数据后,系统实时分析关键指标:
java复制// 血压监测服务
@Service
public class BloodPressureService {
private static final Map<String, Range<Integer>> NORM_RANGES = Map.of(
"systolic", Range.between(90, 140), // 收缩压
"diastolic", Range.between(60, 90) // 舒张压
);
public CheckResult checkAbnormal(BloodPressureRecord record) {
boolean isNormal = NORM_RANGES.get("systolic").contains(record.getSystolic())
&& NORM_RANGES.get("diastolic").contains(record.getDiastolic());
if (!isNormal) {
// 触发短信提醒
smsService.sendAlert(record.getUserId());
}
return new CheckResult(isNormal);
}
}
4. 适老化设计实践
4.1 交互优化要点
- 语音导航:接入阿里云智能语音服务,所有操作都有语音提示
- 容错设计:误触返回按钮时增加二次确认弹窗
- 视觉增强:使用高对比度配色方案(WCAG AA标准)
- 应急通道:长按首页LOGO 5秒可直呼客服
4.2 亲属协管机制
通过"家庭账号"功能,允许子女远程协助父母:
- 扫描专属二维码绑定亲属关系
- 代预约时需短信验证码确认
- 健康数据查看可设置权限粒度控制
5. 部署与性能优化
5.1 服务器配置建议
根据压力测试结果(JMeter模拟1000并发):
- 基础配置:4核8G云服务器(突发性能实例不推荐)
- JVM参数:
bash复制
-Xms2048m -Xmx2048m -XX:MaxMetaspaceSize=512m -XX:+UseG1GC -XX:MaxGCPauseMillis=200 - 数据库:配置连接池(建议HikariCP)
yaml复制spring: datasource: hikari: maximum-pool-size: 20 connection-timeout: 30000
code复制
### 5.2 缓存策略设计
采用多级缓存应对挂号高峰:
1. **本地缓存**:Caffeine(存储科室医生列表)
2. **分布式缓存**:Redis(存储剩余号源)
3. **防超卖**:Redis原子计数器 + 乐观锁
```java
public boolean grabAppointment(Long scheduleId) {
String lockKey = "appt:lock:" + scheduleId;
// 分布式锁防止重复预约
boolean locked = redisTemplate.opsForValue()
.setIfAbsent(lockKey, "1", 30, TimeUnit.SECONDS);
if (!locked) {
throw new BusinessException("操作太频繁");
}
try {
// 乐观锁更新
int updated = appointmentMapper.updateRemain(
scheduleId,
appointmentMapper.selectRemain(scheduleId) - 1);
return updated > 0;
} finally {
redisTemplate.delete(lockKey);
}
}
6. 安全防护措施
6.1 医疗数据加密
敏感字段采用AES-256加密存储:
java复制@Converter
public class CryptoConverter implements AttributeConverter<String, String> {
private static final String KEY = "secureKey123!";
@Override
public String convertToDatabaseColumn(String attribute) {
return AES.encrypt(attribute, KEY);
}
@Override
public String convertToEntityAttribute(String dbData) {
return AES.decrypt(dbData, KEY);
}
}
6.2 审计日志方案
所有数据变更记录完整操作轨迹:
sql复制CREATE TABLE `data_audit_log` (
`id` bigint NOT NULL AUTO_INCREMENT,
`operation_type` varchar(20) NOT NULL,
`table_name` varchar(50) NOT NULL,
`record_id` bigint NOT NULL,
`old_value` json DEFAULT NULL,
`new_value` json DEFAULT NULL,
`operator` varchar(50) NOT NULL,
`operation_time` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `idx_record` (`table_name`,`record_id`)
);
7. 测试与调优实录
7.1 性能瓶颈排查
通过Arthas工具发现的问题:
- N+1查询问题:使用MyBatis-Plus的
@TableField(exist=false)优化关联查询 - 日志同步阻塞:改用AsyncAppender异步写日志
- 分页查询慢:添加
covering index优化
7.2 兼容性测试要点
- 浏览器:重点测试IE11的polyfill方案
- 输入法:确保搜狗、百度等老年常用输入法兼容
- 屏幕阅读器:通过NVDA测试无障碍访问
8. 项目演进方向
- 智能分诊:接入NLP引擎解析症状描述
- 用药提醒:对接药盒IoT设备
- 远程会诊:集成WebRTC视频通话
- 健康画像:基于Spark构建用户健康模型
在开发过程中,我特别总结了几个关键经验:数据库字段一定要预留足够长度(如身份证号应设18位+2预留),接口参数必须做严格校验(防止SQL注入),发布前务必进行全链路压测。这些看似基础的要点,在实际运营中却能避免很多严重问题。