1. 项目背景与核心需求
美容行业近年来呈现爆发式增长态势,传统电话预约方式已经无法满足现代消费者的需求。基于SSM框架的美容店线上预约系统正是为解决这一痛点而设计。这个系统要实现的核心功能包括:客户在线预约、服务项目管理、技师排班、订单处理等完整业务流程。
我去年参与开发过类似项目,发现美容行业对线上预约系统有几个特殊需求:需要支持服务项目的时间段精确预约(比如一个面部护理需要90分钟)、要能直观展示技师的工作日程、还要考虑不同服务项目之间的时间间隔(比如染发和烫发不能连续安排)。这些业务细节都会直接影响系统的数据结构设计。
2. 技术选型与框架搭建
2.1 SSM框架组合解析
我们选择SSM(Spring+SpringMVC+MyBatis)这套经典JavaWeb技术栈,主要基于以下考虑:
- Spring的IoC和AOP特性让系统更易维护扩展
- SpringMVC的拦截器非常适合做权限控制
- MyBatis的灵活性可以应对复杂的美容业务查询
实际开发中,我推荐使用Maven管理依赖。pom.xml中需要特别注意的依赖包括:
xml复制<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.18</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
2.2 数据库设计要点
美容预约系统的数据库设计有几个关键点:
- 服务项目表要包含服务时长字段
- 技师表需要关联可提供的服务项目
- 预约表要记录具体的服务时间段
我建议使用MySQL的DATETIME类型存储预约时间,配合触发器实现时间冲突检测。一个典型的预约表结构如下:
sql复制CREATE TABLE `appointment` (
`id` int NOT NULL AUTO_INCREMENT,
`customer_id` int NOT NULL,
`technician_id` int NOT NULL,
`service_id` int NOT NULL,
`start_time` datetime NOT NULL,
`end_time` datetime NOT NULL,
`status` tinyint DEFAULT '0',
PRIMARY KEY (`id`),
KEY `idx_technician_time` (`technician_id`,`start_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
3. 核心功能实现细节
3.1 预约时间冲突检测
这是系统最核心的算法,我总结了三种实现方案:
- 数据库层面使用触发器检查
- 应用层使用乐观锁
- 使用Redis分布式锁
经过实际测试,我最终选择了方案2,在Service层实现:
java复制public boolean checkTimeConflict(int technicianId, LocalDateTime start, LocalDateTime end) {
List<Appointment> exists = appointmentMapper.selectByTechnicianAndTime(
technicianId, start.minusMinutes(30), end.plusMinutes(30));
return !exists.isEmpty();
}
3.2 技师排班可视化
前端使用FullCalendar组件展示技师日程,后端需要特别注意:
- 时间格式统一使用ISO8601标准
- 考虑时区问题
- 返回数据要包含预约状态信息
一个实用的Controller写法:
java复制@GetMapping("/schedule/{techId}")
@ResponseBody
public List<ScheduleVO> getSchedule(
@PathVariable int techId,
@RequestParam String start,
@RequestParam String end) {
LocalDateTime startTime = LocalDateTime.parse(start);
LocalDateTime endTime = LocalDateTime.parse(end);
return scheduleService.getSchedule(techId, startTime, endTime);
}
4. 答辩常见问题与应对策略
4.1 技术相关问题
Q:为什么选择SSM而不是SpringBoot?
A:SSM更适合教学演示,可以更清晰地展示各层配置。SpringBoot虽然开发效率高,但隐藏了很多实现细节。
Q:如何处理高并发下的预约冲突?
A:我们采用乐观锁+重试机制。具体实现是在更新时检查版本号:
java复制@Transactional
public boolean confirmAppointment(int id, int version) {
Appointment app = appointmentMapper.selectById(id);
if(app.getVersion() != version){
throw new OptimisticLockException();
}
// 其他业务逻辑
}
4.2 业务逻辑问题
Q:如何保证预约时间的合理性?
A:我们在三个层面进行控制:
- 前端限制可选时间段
- 后端校验服务时长
- 数据库触发器二次确认
Q:系统如何防止重复预约?
A:采用手机号验证码+IP限制的组合策略,关键代码:
java复制@RateLimiter(value = 5, key = "#phone")
public String sendVerifyCode(String phone) {
// 发送短信逻辑
}
5. 开发中的经验教训
- 时间处理要特别注意:
- 始终使用Java 8的Time API
- 数据库连接要设置时区参数
- 前端传递时间要明确时区信息
- MyBatis使用建议:
- 复杂查询使用注解+XML混合模式
- 批量操作要使用BatchExecutor
- 关联查询考虑使用ResultMap嵌套
- 性能优化点:
- 技师日程查询添加缓存
- 预约列表使用分页查询
- 静态资源使用CDN加速
这个项目最让我意外的是,美容行业的预约规则出奇地复杂。比如有的项目要求提前24小时取消,有的则需要48小时;不同级别的技师可以享受不同的提成比例。这些业务规则最后我们都通过策略模式来实现,大大提高了系统的可维护性。
