在医疗行业数字化转型的浪潮中,传统线下挂号模式的弊端日益凸显——患者排队耗时、医院管理低效、医疗资源分配不均。为解决这些痛点,我们设计并实现了一套基于SSM(Spring + SpringMVC + MyBatis)架构的智慧医疗预约服务平台。该系统将挂号预约流程全面线上化,通过分层解耦的架构设计,为患者提供便捷的就医通道,同时为医院管理者提供高效的资源调度工具。
系统采用经典的三层架构模式,实现了业务逻辑的清晰分离。表现层使用SpringMVC框架处理Web请求,通过@Controller注解简化了请求映射配置,并结合RESTful风格接口返回JSON数据。业务层基于Spring框架的IoC容器管理Bean生命周期,利用声明式事务管理确保数据一致性。持久层采用MyBatis框架,通过XML映射文件实现灵活的SQL管理,支持动态SQL生成,有效处理复杂的多表关联查询。
在数据库设计方面,系统采用MySQL数据库,设计了8个核心数据表来支撑业务运转。其中,doctor表的设计体现了医疗行业的专业特性:
CREATE TABLE `doctor` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL COMMENT '登录账号',
`password` varchar(100) NOT NULL COMMENT '登录密码',
`name` varchar(50) NOT NULL COMMENT '医生姓名',
`department_id` int(11) NOT NULL COMMENT '所属科室ID',
`title` varchar(50) DEFAULT NULL COMMENT '职称',
`specialty` varchar(200) DEFAULT NULL COMMENT '专业特长',
`work_year` int(11) DEFAULT NULL COMMENT '工作年限',
`max_patients` int(11) DEFAULT '30' COMMENT '单日最大接诊数',
`status` tinyint(4) DEFAULT '1' COMMENT '状态:0-停诊 1-出诊',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `username_unique` (`username`),
KEY `fk_doctor_department` (`department_id`),
CONSTRAINT `fk_doctor_department` FOREIGN KEY (`department_id`)
REFERENCES `department` (`id`) ON DELETE RESTRICT ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='医生信息表';
该表通过department_id外键与科室表建立关联,确保医生数据的规范性。max_patients字段实现了号源管控,status字段支持动态停复诊管理。另一核心表appointment的设计则重点关注事务一致性:
CREATE TABLE `appointment` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`patient_id` int(11) NOT NULL COMMENT '患者ID',
`doctor_id` int(11) NOT NULL COMMENT '医生ID',
`appoint_date` date NOT NULL COMMENT '预约日期',
`time_slot` varchar(20) NOT NULL COMMENT '时间段',
`status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态:0-待确认 1-已确认 2-已取消 3-已完成',
`symptoms` text COMMENT '症状描述',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP,
`confirm_time` datetime DEFAULT NULL COMMENT '确认时间',
PRIMARY KEY (`id`),
KEY `idx_doctor_date` (`doctor_id`,`appoint_date`),
KEY `idx_patient` (`patient_id`),
CONSTRAINT `fk_appointment_doctor` FOREIGN KEY (`doctor_id`)
REFERENCES `doctor` (`id`) ON DELETE CASCADE,
CONSTRAINT `fk_appointment_patient` FOREIGN KEY (`patient_id`)
REFERENCES `patient` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='预约记录表';
通过idx_doctor_date复合索引优化查询性能,外键约束保证数据完整性,status状态机设计完整覆盖预约生命周期。
系统核心功能实现体现了严谨的业务逻辑设计。在医生排班管理模块,Service层实现了号源冲突检测机制:
@Service
@Transactional
public class AppointmentServiceImpl implements AppointmentService {
@Autowired
private AppointmentMapper appointmentMapper;
@Override
public ApiResponse makeAppointment(AppointmentDTO dto) {
// 检查医生当日预约数量是否已达上限
Integer currentCount = appointmentMapper.countByDoctorAndDate(
dto.getDoctorId(), dto.getAppointDate());
Doctor doctor = doctorMapper.selectById(dto.getDoctorId());
if (currentCount >= doctor.getMaxPatients()) {
return ApiResponse.error("该医生当日号源已满");
}
// 检查同一时间段是否已有预约
Appointment exist = appointmentMapper.selectByDoctorAndTime(
dto.getDoctorId(), dto.getAppointDate(), dto.getTimeSlot());
if (exist != null) {
return ApiResponse.error("该时间段已被预约");
}
Appointment appointment = new Appointment();
BeanUtils.copyProperties(dto, appointment);
appointment.setStatus(0); // 待确认状态
appointmentMapper.insert(appointment);
return ApiResponse.success("预约申请已提交,等待医生确认");
}
}
患者预约功能通过前端页面实现直观的操作界面。患者登录后可以查看科室医生排班情况,选择合适的时间段进行预约。

医生工作台模块为医务人员提供了完整的患者管理功能。医生可以查看待确认的预约列表,根据患者病情描述决定是否接诊:
@RestController
@RequestMapping("/doctor")
public class DoctorController {
@Autowired
private AppointmentService appointmentService;
@PostMapping("/confirmAppointment")
public ApiResponse confirmAppointment(@RequestParam Integer appointmentId,
@RequestParam Boolean confirmed) {
Appointment appointment = appointmentMapper.selectById(appointmentId);
if (appointment == null) {
return ApiResponse.error("预约记录不存在");
}
if (confirmed) {
appointment.setStatus(1); // 已确认
appointment.setConfirmTime(new Date());
} else {
appointment.setStatus(2); // 已取消
}
appointmentMapper.updateById(appointment);
// 发送通知短信给患者
smsService.sendAppointmentResult(appointment.getPatient().getPhone(),
confirmed);
return ApiResponse.success("操作成功");
}
}

管理员模块具备完整的系统管理能力,包括科室管理、医生信息维护、公告发布等功能。科室管理页面支持动态添加和调整医疗科室:
@Service
public class DepartmentServiceImpl implements DepartmentService {
@Autowired
private DepartmentMapper departmentMapper;
@Override
public ApiResponse addDepartment(Department department) {
// 检查科室名称是否重复
Department exist = departmentMapper.selectByName(department.getName());
if (exist != null) {
return ApiResponse.error("科室名称已存在");
}
department.setCreateTime(new Date());
department.setStatus(1); // 启用状态
departmentMapper.insert(department);
return ApiResponse.success("科室添加成功");
}
@Override
@Transactional
public ApiResponse deleteDepartment(Integer id) {
// 检查科室下是否有医生
Integer doctorCount = doctorMapper.countByDepartment(id);
if (doctorCount > 0) {
return ApiResponse.error("该科室下存在医生,无法删除");
}
departmentMapper.deleteById(id);
return ApiResponse.success("科室删除成功");
}
}

系统实体模型设计严格遵循领域驱动设计原则。核心实体Appointment通过贫血模型实现数据持久化,同时通过DTO对象处理前后端数据交互:
public class Appointment {
private Integer id;
private Integer patientId;
private Integer doctorId;
private Date appointDate;
private String timeSlot;
private Integer status;
private String symptoms;
private Date createTime;
private Date confirmTime;
// 关联对象
private Patient patient;
private Doctor doctor;
// getter/setter方法
public Integer getId() { return id; }
public void setId(Integer id) { this.id = id; }
public Integer getPatientId() { return patientId; }
public void setPatientId(Integer patientId) { this.patientId = patientId; }
// 其他getter/setter...
}
@Data
public class AppointmentDTO {
@NotNull(message = "患者ID不能为空")
private Integer patientId;
@NotNull(message = "医生ID不能为空")
private Integer doctorId;
@Future(message = "预约日期必须为未来时间")
private Date appointDate;
@NotBlank(message = "时间段不能为空")
private String timeSlot;
@Size(max = 500, message = "症状描述不能超过500字")
private String symptoms;
}
数据访问层采用MyBatis的注解与XML混合配置模式,复杂查询使用XML配置实现动态SQL:
<!-- AppointmentMapper.xml -->
<mapper namespace="com.hospital.mapper.AppointmentMapper">
<resultMap id="AppointmentDetailMap" type="com.hospital.entity.Appointment">
<id column="id" property="id"/>
<result column="appoint_date" property="appointDate"/>
<result column="time_slot" property="timeSlot"/>
<result column="status" property="status"/>
<result column="symptoms" property="symptoms"/>
<result column="create_time" property="createTime"/>
<result column="confirm_time" property="confirmTime"/>
<association property="patient" javaType="com.hospital.entity.Patient">
<id column="patient_id" property="id"/>
<result column="patient_name" property="name"/>
<result column="patient_phone" property="phone"/>
</association>
<association property="doctor" javaType="com.hospital.entity.Doctor">
<id column="doctor_id" property="id"/>
<result column="doctor_name" property="name"/>
<result column="title" property="title"/>
</association>
</resultMap>
<select id="selectByDoctorWithDetail" parameterType="map" resultMap="AppointmentDetailMap">
SELECT a.*, p.name as patient_name, p.phone as patient_phone,
d.name as doctor_name, d.title
FROM appointment a
LEFT JOIN patient p ON a.patient_id = p.id
LEFT JOIN doctor d ON a.doctor_id = d.id
WHERE a.doctor_id = #{doctorId}
<if test="startDate != null">
AND a.appoint_date >= #{startDate}
</if>
<if test="endDate != null">
AND a.appoint_date <= #{endDate}
</if>
ORDER BY a.appoint_date DESC, a.create_time DESC
</select>
</mapper>
系统配置层面,通过Spring的Java Config方式替代传统XML配置,提升配置的可读性和类型安全性:
@Configuration
@EnableWebMvc
@ComponentScan("com.hospital")
@EnableTransactionManagement
public class AppConfig implements WebMvcConfigurer {
@Bean
public DataSource dataSource() {
HikariDataSource dataSource = new HikariDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/hospital_db?useUnicode=true&characterEncoding=utf8");
dataSource.setUsername("root");
dataSource.setPassword("password");
dataSource.setMaximumPoolSize(20);
dataSource.setMinimumIdle(5);
return dataSource;
}
@Bean
public SqlSessionFactoryBean sqlSessionFactory() throws Exception {
SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setTypeAliasesPackage("com.hospital.entity");
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
sessionFactory.setMapperLocations(resolver.getResources("classpath:mapper/*.xml"));
return sessionFactory;
}
@Bean
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource());
}
}
系统在以下方面具备进一步优化的潜力:
分布式号源管理:当前系统采用单数据库部署,未来可引入Redis集群实现分布式锁机制,防止超卖问题。通过Redis原子操作确保在高并发场景下号源计算的准确性。
智能推荐算法:集成机器学习算法,根据患者症状描述、历史就诊记录、医生专业特长等维度,智能推荐最适合的科室和医生,提升匹配精度。
微服务架构重构:将单体应用拆分为患者服务、医生服务、预约服务、排班服务等独立微服务,通过Spring Cloud实现服务治理,提升系统可扩展性和容错能力。
移动端深度集成:开发React Native跨平台移动应用,集成推送通知、扫码签到、电子病历查看等功能,为患者提供全流程移动化服务。
大数据分析平台:构建基于Hadoop/Spark的数据分析模块,对就诊流量、疾病谱系、医生工作效率等指标进行多维度分析,为医院管理决策提供数据支持。
智慧医疗预约服务平台通过严谨的架构设计和深度的业务逻辑实现,建立了完整的线上挂号预约生态体系。系统在保证数据一致性和业务完整性的前提下,显著提升了医疗资源的利用效率和患者就诊体验,为医疗机构的数字化转型提供了坚实的技术基础。