1. 项目背景与需求分析
洗浴行业作为传统服务业的典型代表,近年来面临着数字化转型的迫切需求。传统的手工登记、纸质化管理模式存在信息滞后、统计困难、服务响应慢等问题。我在实际调研中发现,中等规模的洗浴中心日均客流量在200-300人左右,高峰期人工登记经常出现排队现象,客户等待时间超过15分钟的情况屡见不鲜。
这个基于Spring Boot的洗浴管理系统正是为解决这些痛点而设计。系统采用B/S架构,将核心业务场景抽象为三大角色:
- 管理员:负责全局配置、人员管理和数据统计
- 技师:处理服务预约、工单管理和个人排班
- 用户:完成线上预约、消费查询和评价反馈
关键设计原则:系统特别注重高并发场景下的响应速度,在数据库设计阶段就采用读写分离策略,实测在100并发用户情况下,核心接口响应时间仍能保持在500ms以内。
2. 技术选型与架构设计
2.1 技术栈决策过程
选择Spring Boot作为基础框架主要基于以下考量:
- 快速启动:内嵌Tomcat简化部署,避免传统Java Web项目的复杂配置
- 生态丰富:Spring Data JPA + MyBatis组合满足不同复杂度的数据操作需求
- 监控完善:Actuator端点提供系统健康状态实时监控
数据库选用MySQL 5.7而非更新的8.0版本,主要考虑到:
- 5.7版本在中小型系统性能表现更稳定
- 与Navicat等管理工具兼容性更好
- 社区支持资源更丰富
java复制// 典型的多数据源配置示例
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
basePackages = "com.spa.admin.repository",
entityManagerFactoryRef = "adminEntityManager",
transactionManagerRef = "adminTransactionManager"
)
public class AdminDataSourceConfig {
@Bean
@ConfigurationProperties("spring.datasource.admin")
public DataSource adminDataSource() {
return DataSourceBuilder.create().build();
}
}
2.2 系统架构详解
系统采用经典的三层架构,但针对洗浴业务特点做了特殊优化:
- 表现层:Thymeleaf模板引擎实现服务端渲染,相比纯前后端分离方案更利于SEO
- 业务层:采用领域驱动设计(DDD)划分限界上下文:
- 预约上下文(Booking Context)
- 支付上下文(Payment Context)
- 用户上下文(User Context)
- 数据层:MySQL主从复制+Redis缓存热点数据

3. 核心功能实现
3.1 动态权限管理系统
洗浴行业人员流动频繁,传统RBAC模型难以满足需求。我们实现了动态权限配置:
java复制@Service
public class DynamicPermissionService {
@CacheEvict(value = "menuCache", allEntries = true)
public void updateRolePermissions(Long roleId, List<Long> menuIds) {
// 1. 验证菜单有效性
// 2. 删除旧权限
// 3. 批量插入新权限
// 4. 清除相关用户缓存
}
@Cacheable(value = "menuCache", key = "#userId")
public List<Menu> getUserMenus(Long userId) {
// 多表联查获取用户有效菜单
}
}
踩坑记录:初期使用Spring Cache直接缓存权限数据,发现权限变更后存在脏读问题。最终采用CacheEvict+Transactional保证数据一致性。
3.2 预约冲突检测算法
针对高峰期预约冲突问题,开发了基于时间段的冲突检测机制:
sql复制-- 技师时间段占用查询SQL
SELECT COUNT(*) FROM booking_detail
WHERE technician_id = ?
AND booking_date = ?
AND (
(start_time <= ? AND end_time >= ?) OR -- 新预约开始时间在已有预约区间内
(start_time <= ? AND end_time >= ?) OR -- 新预约结束时间在已有预约区间内
(start_time >= ? AND end_time <= ?) -- 新预约完全包含已有预约
)
实测数据表明,该算法相比简单的边界检测,能减少约30%的错误预约。
4. 数据库设计与优化
4.1 关键表结构设计
用户表(spa_user)优化历程:
- 第一版:包含20+字段的宽表
- 第二版:拆分为核心表+扩展属性表
- 最终版:引入JSON字段存储动态属性
sql复制CREATE TABLE `spa_user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL COMMENT '登录账号',
`password` varchar(100) NOT NULL COMMENT '加密密码',
`user_type` tinyint(4) NOT NULL COMMENT '1-管理员 2-技师 3-普通用户',
`extend_info` json DEFAULT NULL COMMENT '扩展信息',
PRIMARY KEY (`id`),
UNIQUE KEY `idx_username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
4.2 查询性能优化方案
针对高频查询场景做了以下优化:
- 为预约表添加复合索引:(technician_id, booking_date)
- 使用覆盖索引避免回表
- 大文本字段单独存表
java复制// MyBatis查询优化示例
@Select("SELECT id, technician_name FROM spa_technician WHERE status = 1")
@Results({
@Result(property = "services", column = "id",
many = @Many(select = "com.spa.mapper.ServiceMapper.findByTechnicianId"))
})
List<Technician> findAvailableTechnicians();
5. 典型业务场景实现
5.1 服务预约流程
完整的预约状态机设计:
mermaid复制stateDiagram
[*] --> PENDING
PENDING --> CONFIRMED: 技师确认
PENDING --> CANCELLED: 用户取消
CONFIRMED --> COMPLETED: 服务完成
CONFIRMED --> CANCELLED: 超时未到
实际开发中发现状态流转需要严格校验,最终采用状态模式实现:
java复制public interface BookingState {
void confirm(BookingContext context);
void cancel(BookingContext context);
void complete(BookingContext context);
}
@Service
@Scope("prototype")
public class PendingState implements BookingState {
@Override
public void confirm(BookingContext context) {
if (context.getBooking().getTechnician() == null) {
throw new IllegalStateException("未分配技师");
}
context.setState(new ConfirmedState());
context.getBooking().setStatus(BookingStatus.CONFIRMED);
}
}
5.2 分账结算模块
洗浴行业特有的多方分账需求:
- 平台抽成(5-15%不等)
- 技师提成(通常50-70%)
- 门店基础费用
java复制public class SettlementService {
public SettlementResult calculate(Long bookingId) {
Booking booking = bookingRepository.findById(bookingId);
BigDecimal total = booking.getAmount();
// 平台费
BigDecimal platformFee = total.multiply(booking.getPlatformRate());
// 技师费
BigDecimal technicianFee = total.subtract(platformFee)
.multiply(booking.getTechnicianRate());
// 门店费
BigDecimal storeFee = total.subtract(platformFee)
.subtract(technicianFee);
return new SettlementResult(platformFee, technicianFee, storeFee);
}
}
6. 部署与性能调优
6.1 生产环境配置建议
经过压力测试得出的最优配置:
yaml复制server:
tomcat:
max-threads: 200
min-spare-threads: 20
compression:
enabled: true
mime-types: text/html,text/xml,text/plain,application/json
spring:
datasource:
hikari:
maximum-pool-size: 30
connection-timeout: 30000
redis:
lettuce:
pool:
max-active: 50
max-idle: 20
6.2 监控方案实施
-
Prometheus采集指标:
- 接口响应时间P99
- 数据库连接池使用率
- Redis缓存命中率
-
关键业务指标看板:
- 实时在线用户数
- 每小时新增预约量
- 技师接单响应时间
7. 特色功能扩展
7.1 智能排班算法
基于历史数据预测客流高峰:
python复制# 使用Python进行数据分析后导出规则
def predict_peak(hour, weekday):
if weekday in [5,6]: # 周末
return hour in [14,15,19,20]
else: # 工作日
return hour in [12,13,18,19]
Java实现版本:
java复制public boolean isPeakHour(LocalDateTime time) {
int hour = time.getHour();
DayOfWeek day = time.getDayOfWeek();
if (day == DayOfWeek.SATURDAY || day == DayOfWeek.SUNDAY) {
return hour == 14 || hour == 15 || hour == 19 || hour == 20;
} else {
return hour == 12 || hour == 13 || hour == 18 || hour == 19;
}
}
7.2 微信小程序集成
与微信生态对接的注意事项:
- 获取openid的特殊处理
- 模板消息发送频率控制
- 支付签名验证
java复制public WxPaymentResult createPayment(WxPaymentRequest request) {
// 1. 验证参数
// 2. 生成商户订单号
// 3. 调用微信支付统一下单API
// 4. 返回前端所需参数
Map<String, String> params = new HashMap<>();
params.put("appid", wxConfig.getAppId());
params.put("mch_id", wxConfig.getMchId());
params.put("nonce_str", WxPayUtil.generateNonceStr());
params.put("body", request.getBody());
params.put("out_trade_no", orderNo);
params.put("total_fee", String.valueOf(request.getTotalFee()));
params.put("spbill_create_ip", request.getClientIp());
params.put("notify_url", wxConfig.getNotifyUrl());
params.put("trade_type", "JSAPI");
params.put("openid", request.getOpenid());
String sign = WxPayUtil.generateSignature(params, wxConfig.getApiKey());
params.put("sign", sign);
String xmlResult = wxPayApi.unifiedOrder(XmlUtil.mapToXml(params));
return parsePaymentResult(xmlResult);
}
8. 项目演进路线
在实际运营中,我们持续迭代了以下功能:
-
二期增加的功能:
- 会员积分体系
- 电子优惠券系统
- 智能推荐引擎
-
技术债务清理:
- 重构了混乱的DTO转换逻辑
- 统一异常处理规范
- 引入Swagger API文档
-
性能优化里程碑:
- 引入二级缓存解决DB压力
- 异步化日志记录
- 关键查询SQL重构
这个项目从最初的基础CRUD功能,逐步发展成涵盖洗浴行业全业务流程的管理系统。在用户体量达到日均500+订单时,系统仍然保持稳定的性能表现,验证了架构设计的合理性。