1. 项目概述
游泳馆管理系统是一个基于Spring Boot框架开发的B/S架构应用,旨在为游泳馆提供全面的数字化管理解决方案。作为一名有多年Java开发经验的工程师,我在实际项目中发现很多游泳馆仍在使用传统的人工登记方式,不仅效率低下,还容易出现数据丢失和统计错误的问题。这个系统正是为了解决这些痛点而设计的。
系统采用前后端分离架构,后端使用Spring Boot+MyBatis Plus技术栈,前端基于Vue.js实现响应式界面。主要功能包括会员管理、票务销售、场地预约、教练排班、财务统计等模块,能够覆盖游泳馆日常运营的各个环节。相比市面上一些功能单一的解决方案,我们这个系统特别强化了数据分析和报表功能,可以帮助管理者更直观地了解经营状况。
2. 系统架构设计
2.1 技术选型解析
在技术选型上,我们经过多次讨论和验证,最终确定了以下技术栈:
后端技术栈:
- Spring Boot 2.7.x:简化配置,快速构建微服务
- MyBatis Plus 3.5.x:增强的ORM框架,减少SQL编写
- Shiro 1.10.x:安全认证和权限控制
- Redis 6.x:缓存热点数据,提升系统响应速度
- MySQL 8.0:关系型数据库存储核心业务数据
前端技术栈:
- Vue 3.x:渐进式前端框架
- Element Plus:UI组件库
- ECharts 5.x:数据可视化图表
- Axios:HTTP请求库
选择这些技术主要基于以下几个考虑:
- Spring Boot的自动配置和起步依赖可以大幅减少项目搭建时间
- MyBatis Plus在MyBatis基础上增强了CRUD操作,开发效率提升明显
- Vue 3的Composition API更适合复杂业务场景的开发
- MySQL作为成熟的关系型数据库,在事务处理和数据一致性方面表现优异
2.2 系统架构详解
系统采用典型的三层架构设计:
code复制表示层(Web层)
├── 用户界面(Vue组件)
├── 管理后台(Vue组件)
└── 移动端H5(适配小程序)
业务逻辑层(Service层)
├── 会员服务
├── 票务服务
├── 场地服务
├── 财务服务
└── 报表服务
数据访问层(DAO层)
├── MyBatis Plus Mapper
├── Redis缓存
└── MySQL数据库
这种分层架构的优势在于:
- 职责分离,各层专注自己的功能
- 便于团队协作开发
- 可维护性和可扩展性强
- 便于单元测试和集成测试
3. 核心功能实现
3.1 会员管理系统
会员管理是游泳馆运营的核心模块,我们设计了完整的会员生命周期管理功能:
会员注册流程:
- 前端收集用户基本信息(姓名、电话、身份证号等)
- 后端验证信息合法性(身份证校验、手机号验证等)
- 生成会员账号和初始密码
- 记录会员注册渠道和时间
- 发送欢迎短信或邮件
java复制// 会员注册核心代码示例
@PostMapping("/register")
public Result register(@Valid @RequestBody MemberRegisterDTO dto) {
// 验证手机号是否已注册
if(memberService.checkMobileExist(dto.getMobile())){
return Result.fail("该手机号已注册");
}
// 密码加密存储
String encryptedPwd = DigestUtils.md5DigestAsHex(dto.getPassword().getBytes());
// 构建会员实体
Member member = new Member();
member.setMobile(dto.getMobile());
member.setPassword(encryptedPwd);
member.setRealName(dto.getRealName());
member.setIdCard(dto.getIdCard());
member.setRegisterTime(LocalDateTime.now());
// 保存会员信息
boolean success = memberService.save(member);
return success ? Result.ok() : Result.fail("注册失败");
}
会员卡管理:
- 支持次卡、时长卡、储值卡等多种卡类型
- 卡状态管理(正常、冻结、过期等)
- 消费记录实时更新
- 余额变动提醒
3.2 场地预约系统
场地预约模块解决了游泳馆高峰期资源分配问题,主要特点包括:
- 智能排期算法:根据历史数据预测高峰期,自动调整可预约时段
- 防冲突机制:确保同一时段同一泳道不会被重复预约
- 迟到处理:超过15分钟未签到自动释放资源
- 预约提醒:提前30分钟短信提醒用户
java复制// 场地预约核心逻辑
public synchronized Result bookSwimLane(BookingDTO dto) {
// 检查时段是否可用
if(!timeSlotService.isAvailable(dto.getLaneId(), dto.getStartTime(), dto.getEndTime())){
return Result.fail("该时段已被预约");
}
// 检查会员卡有效性
MemberCard card = cardService.getById(dto.getCardId());
if(card == null || card.getStatus() != 1){
return Result.fail("会员卡无效");
}
// 扣减卡次或余额
if(card.getType() == 1){ // 次卡
if(card.getRemainTimes() < 1){
return Result.fail("剩余次数不足");
}
card.setRemainTimes(card.getRemainTimes() - 1);
} else { // 储值卡
BigDecimal cost = calculateBookingFee(dto);
if(card.getBalance().compareTo(cost) < 0){
return Result.fail("余额不足");
}
card.setBalance(card.getBalance().subtract(cost));
}
// 创建预约记录
Booking booking = new Booking();
booking.setMemberId(dto.getMemberId());
booking.setLaneId(dto.getLaneId());
booking.setStartTime(dto.getStartTime());
booking.setEndTime(dto.getEndTime());
booking.setStatus(0); // 待使用
// 事务保存
transactionTemplate.execute(status -> {
cardService.updateById(card);
bookingService.save(booking);
return null;
});
// 发送预约成功通知
notifyService.sendBookingSuccess(booking);
return Result.ok(booking);
}
4. 数据库设计
4.1 核心表结构
系统数据库包含20多张表,以下是几个关键表的设计:
会员表(member)
sql复制CREATE TABLE `member` (
`id` bigint NOT NULL AUTO_INCREMENT,
`mobile` varchar(20) NOT NULL COMMENT '手机号',
`password` varchar(64) NOT NULL COMMENT '密码(加密)',
`real_name` varchar(50) DEFAULT NULL COMMENT '真实姓名',
`id_card` varchar(18) DEFAULT NULL COMMENT '身份证号',
`gender` tinyint DEFAULT '0' COMMENT '性别(0未知1男2女)',
`birthday` date DEFAULT NULL COMMENT '生日',
`avatar` varchar(255) DEFAULT NULL COMMENT '头像',
`status` tinyint DEFAULT '1' COMMENT '状态(0禁用1正常)',
`register_time` datetime NOT NULL COMMENT '注册时间',
`last_login_time` datetime DEFAULT NULL COMMENT '最后登录时间',
PRIMARY KEY (`id`),
UNIQUE KEY `idx_mobile` (`mobile`),
KEY `idx_id_card` (`id_card`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='会员信息表';
会员卡表(member_card)
sql复制CREATE TABLE `member_card` (
`id` bigint NOT NULL AUTO_INCREMENT,
`member_id` bigint NOT NULL COMMENT '会员ID',
`card_no` varchar(32) NOT NULL COMMENT '卡号',
`type` tinyint NOT NULL COMMENT '卡类型(1次卡2时长卡3储值卡)',
`total_value` int DEFAULT NULL COMMENT '总次数/总天数/总金额',
`remain_value` int DEFAULT NULL COMMENT '剩余次数/剩余天数/剩余金额',
`start_date` date NOT NULL COMMENT '开始日期',
`end_date` date NOT NULL COMMENT '结束日期',
`status` tinyint DEFAULT '1' COMMENT '状态(0禁用1正常2冻结3过期)',
`create_time` datetime NOT NULL COMMENT '创建时间',
PRIMARY KEY (`id`),
UNIQUE KEY `idx_card_no` (`card_no`),
KEY `idx_member_id` (`member_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='会员卡表';
4.2 数据库优化策略
在实际运行中,我们针对数据库性能做了以下优化:
-
索引优化:
- 为所有外键字段添加索引
- 为高频查询条件字段添加组合索引
- 定期使用EXPLAIN分析慢查询
-
查询优化:
- 避免SELECT *,只查询需要的字段
- 复杂查询拆分为多个简单查询
- 使用JOIN替代子查询
-
缓存策略:
- 热点数据缓存到Redis
- 二级缓存配置
- 定期清理无效缓存
5. 系统安全设计
5.1 认证与授权
系统采用Shiro框架实现安全控制,主要安全措施包括:
-
密码安全:
- 使用MD5加盐加密存储
- 登录失败次数限制
- 密码强度校验
-
权限控制:
- 基于角色的访问控制(RBAC)
- 细粒度的权限配置
- 操作日志审计
java复制// Shiro配置示例
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
factoryBean.setSecurityManager(securityManager);
// 拦截规则
Map<String, String> filterMap = new LinkedHashMap<>();
filterMap.put("/api/login", "anon");
filterMap.put("/api/register", "anon");
filterMap.put("/static/**", "anon");
filterMap.put("/api/**", "authc");
factoryBean.setFilterChainDefinitionMap(filterMap);
return factoryBean;
}
5.2 数据安全
-
敏感数据加密:
- 身份证号、手机号等敏感信息加密存储
- 数据库连接信息加密
- 配置文件敏感信息加密
-
防SQL注入:
- 使用预编译语句
- MyBatis参数绑定
- 输入参数过滤
-
XSS防护:
- 前端输入过滤
- 后端输出转义
- CSP策略配置
6. 系统测试与部署
6.1 测试策略
我们采用分层测试策略确保系统质量:
- 单元测试:使用JUnit+Mockito测试Service层
- 集成测试:测试模块间交互
- API测试:使用Postman测试接口
- UI测试:使用Selenium测试前端功能
- 性能测试:使用JMeter模拟高并发
6.2 部署方案
系统支持多种部署方式:
传统部署:
- 打包Spring Boot应用为JAR
- 部署到Tomcat服务器
- 配置Nginx反向代理
- 配置MySQL主从复制
容器化部署:
dockerfile复制# Dockerfile示例
FROM openjdk:11-jre
WORKDIR /app
COPY target/swim-manage.jar .
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "swim-manage.jar"]
CI/CD流程:
- 代码提交触发GitHub Actions
- 自动运行单元测试
- 构建Docker镜像
- 推送到私有镜像仓库
- 滚动更新K8s集群
7. 项目总结与扩展
在开发这个游泳馆管理系统的过程中,我积累了一些宝贵的经验:
-
复杂业务逻辑处理:对于预约冲突检测这类复杂逻辑,采用状态机模式可以大大简化代码复杂度。
-
性能优化:在高并发场景下,使用Redis分布式锁替代synchronized关键字,系统吞吐量提升了3倍。
-
可扩展性设计:通过策略模式实现不同的会员卡类型计算逻辑,后续新增卡类型只需添加新策略即可。
未来可以考虑的扩展方向:
- 接入微信小程序,提供移动端入口
- 增加人脸识别签到功能
- 开发大数据分析模块,提供经营决策支持
- 实现多游泳馆连锁管理功能
这个项目从需求分析到最终上线历时3个月,期间遇到了不少挑战,但最终的成果证明这些努力都是值得的。系统目前已经在本地两家游泳馆投入使用,运行稳定,用户反馈良好。