毕业设计实战:基于Spring Boot的健身房管理系统毕设全流程指南✨

57 阅读10分钟

毕业设计实战:基于Spring Boot的健身房管理系统毕设全流程指南✨

去年做健身房管理系统毕设时,我在会员管理和课程预约的关联逻辑上卡了整整一周——一开始没处理"会员到期"逻辑,过期会员还能预约课程,导师演示时直接发现了这个业务漏洞😫 经过反复修改优化,终于总结出了这套健身房管理系统毕设实战经验!

一、需求分析:抓住健身房管理核心业务

刚开始我想做一个"万能健身系统",包含了营养管理、体测分析、社交功能等模块,结果导师说"重点不突出,核心会员管理和课程预约不清晰"。后来明白,健身房管理系统要围绕会员-课程-器材这个核心业务链展开。

1. 核心用户角色与功能

系统主要面向两类用户,功能定位要精准:

  • 管理员端(经营管理核心):

    • 会员管理:办理会员卡、设置到期时间、会员信息维护
    • 教练管理:录入教练信息、设置教练专长、管理教练排班
    • 课程管理:发布团课信息、设置课程容量、管理课程预约
    • 器材管理:登记健身器材、维护器材状态、管理器材使用
    • 健身房管理:维护分店信息、设置营业时间
  • 会员端(服务体验核心):

    • 课程预约:查看课程表、预约团课课程、取消预约
    • 会员信息:查看会员状态、剩余有效期、消费记录
    • 教练查询:查看教练信息、专长领域、用户评价
    • 器材查看:了解器材信息、使用指南

2. 需求分析实战技巧

  • 实地调研很重要:我实地走访了3家健身房,发现他们最需要"会员到期自动提醒"功能,于是重点设计了会员状态管理
  • 绘制业务流程图:用DrawIO画出"会员办卡→预约课程→上课记录"的完整流程,答辩时清晰展示业务逻辑
  • 明确业务规则:如"会员到期前7天提醒""课程开始前2小时可取消""同一时段只能预约一门课程"等约束条件

3. 可行性分析要点

  • 技术可行性:Spring Boot+MySQL技术成熟,开发资料丰富
  • 经济可行性:全部使用开源工具,零开发成本
  • 操作可行性:界面设计参考主流健身APP,用户上手快

二、技术选型:稳定高效的开发方案

曾经尝试用微服务架构,结果服务注册发现配置卡了3天,最终选择单体架构,开发效率大大提升!

1. 技术栈选择理由

技术组件选择理由避坑提醒
Spring Boot 2.7配置简单,内嵌Tomcat不要用3.x,兼容性问题多
MySQL 8.0数据关系明确,适合会员管理系统记得配置时区为东八区
JSP + Bootstrap开发速度快,学习成本低Bootstrap用3.x版本
MyBatisSQL可控性强,方便优化注意XML配置文件的路径

2. 开发环境搭建

# 创建Spring Boot项目
使用Spring Initializr
选择Web、MySQL、MyBatis依赖

# 数据库配置
spring.datasource.url=jdbc:mysql://localhost:3306/gym_db?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=123456

三、数据库设计:健身业务数据建模

最初设计时将会员信息和课程预约放在同一张表,导致查询性能低下。重新设计后按业务模块分表,系统响应速度大幅提升。

1. 核心数据表设计

会员表(yonghu)

CREATE TABLE `yonghu` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `yonghu_name` varchar(100) NOT NULL COMMENT '会员姓名',
  `yonghu_phone` varchar(20) NOT NULL COMMENT '手机号',
  `yonghu_id_number` varchar(20) DEFAULT NULL COMMENT '身份证号',
  `yonghu_photo` varchar(255) DEFAULT NULL COMMENT '头像',
  `yonghu_email` varchar(100) DEFAULT NULL COMMENT '邮箱',
  `huiyuan_type` int(11) DEFAULT '1' COMMENT '会员类型:1普通/2VIP',
  `daoqi_time` date NOT NULL COMMENT '到期日期',
  `insert_time` datetime DEFAULT NULL COMMENT '注册时间',
  `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_phone` (`yonghu_phone`),
  KEY `idx_daoqi` (`daoqi_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='会员表';

课程预约表(kecheng_yuyue)

CREATE TABLE `kecheng_yuyue` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `yonghu_id` int(11) NOT NULL COMMENT '会员ID',
  `kecheng_id` int(11) NOT NULL COMMENT '课程ID',
  `yuyue_time` datetime NOT NULL COMMENT '预约时间',
  `yuyue_status` int(11) DEFAULT '0' COMMENT '预约状态:0已预约/1已取消/2已完成',
  `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `fk_yonghu` (`yonghu_id`),
  KEY `fk_kecheng` (`kecheng_id`),
  UNIQUE KEY `uk_yonghu_kecheng` (`yonghu_id`, `kecheng_id`, `yuyue_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='课程预约表';

课程表(kecheng)

CREATE TABLE `kecheng` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `kecheng_name` varchar(100) NOT NULL COMMENT '课程名称',
  `jiaolian_id` int(11) NOT NULL COMMENT '教练ID',
  `jianshenfang_id` int(11) NOT NULL COMMENT '健身房ID',
  `kecheng_types` int(11) DEFAULT NULL COMMENT '课程类型',
  `kecheng_time` datetime NOT NULL COMMENT '上课时间',
  `kecheng_duration` int(11) DEFAULT '60' COMMENT '课程时长(分钟)',
  `max_people` int(11) DEFAULT '20' COMMENT '最大人数',
  `signed_people` int(11) DEFAULT '0' COMMENT '已报名人数',
  `kecheng_content` text COMMENT '课程介绍',
  `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='课程表';

2. 表关系设计要点

  • 状态字段设计:预约状态(已预约/已取消/已完成)、会员状态(正常/即将到期/已到期)
  • 唯一约束:同一会员同一时间段只能预约一门课程
  • 容量控制:课程报名人数不能超过最大容量

四、核心功能实现与代码详解

1. 课程预约模块(会员端核心功能)

Service层实现:

@Service
public class KechengYuyueServiceImpl implements KechengYuyueService {
    
    @Autowired
    private KechengYuyueMapper kechengYuyueMapper;
    
    @Autowired
    private KechengMapper kechengMapper;
    
    @Autowired
    private YonghuMapper yonghuMapper;

    @Override
    @Transactional
    public void yuyueKecheng(Integer kechengId, Integer yonghuId) {
        // 1. 检查会员状态
        YonghuEntity yonghu = yonghuMapper.selectById(yonghuId);
        if (yonghu.getDaoqiTime().before(new Date())) {
            throw new RuntimeException("会员已到期,请先续费");
        }
        
        // 2. 检查课程容量
        KechengEntity kecheng = kechengMapper.selectById(kechengId);
        if (kecheng.getSignedPeople() >= kecheng.getMaxPeople()) {
            throw new RuntimeException("课程已满员,无法预约");
        }
        
        // 3. 检查时间冲突
        Integer conflictCount = kechengYuyueMapper.selectCount(
            new EntityWrapper<KechengYuyueEntity>()
                .eq("yonghu_id", yonghuId)
                .eq("yuyue_status", 0) // 已预约状态
                .eq("DATE(yuyue_time)", 
                    new SimpleDateFormat("yyyy-MM-dd").format(kecheng.getKechengTime()))
        );
        if (conflictCount > 0) {
            throw new RuntimeException("该时段已预约其他课程");
        }
        
        // 4. 检查是否重复预约
        Integer existCount = kechengYuyueMapper.selectCount(
            new EntityWrapper<KechengYuyueEntity>()
                .eq("yonghu_id", yonghuId)
                .eq("kecheng_id", kechengId)
                .in("yuyue_status", Arrays.asList(0, 2)) // 已预约和已完成
        );
        if (existCount > 0) {
            throw new RuntimeException("已预约过该课程");
        }
        
        // 5. 创建预约记录
        KechengYuyueEntity yuyue = new KechengYuyueEntity();
        yuyue.setYonghuId(yonghuId);
        yuyue.setKechengId(kechengId);
        yuyue.setYuyueTime(kecheng.getKechengTime());
        yuyue.setYuyueStatus(0); // 已预约
        kechengYuyueMapper.insert(yuyue);
        
        // 6. 更新课程报名人数
        kecheng.setSignedPeople(kecheng.getSignedPeople() + 1);
        kechengMapper.updateById(kecheng);
    }

    @Override
    @Transactional
    public void cancelYuyue(Integer yuyueId) {
        KechengYuyueEntity yuyue = kechengYuyueMapper.selectById(yuyueId);
        if (yuyue == null) {
            throw new RuntimeException("预约记录不存在");
        }
        
        // 检查取消时间(课程开始前2小时可取消)
        Date now = new Date();
        long diff = yuyue.getYuyueTime().getTime() - now.getTime();
        long hours = diff / (1000 * 60 * 60);
        if (hours < 2) {
            throw new RuntimeException("课程开始前2小时内不可取消");
        }
        
        // 更新预约状态
        yuyue.setYuyueStatus(1); // 已取消
        kechengYuyueMapper.updateById(yuyue);
        
        // 更新课程报名人数
        KechengEntity kecheng = kechengMapper.selectById(yuyue.getKechengId());
        kecheng.setSignedPeople(kecheng.getSignedPeople() - 1);
        kechengMapper.updateById(kecheng);
    }
}

Controller层:

@Controller
@RequestMapping("/member/yuyue")
public class MemberYuyueController {
    
    @Autowired
    private KechengYuyueService kechengYuyueService;

    @PostMapping("/yuyue")
    public String yuyueKecheng(Integer kechengId, HttpServletRequest request) {
        try {
            // 获取当前登录会员
            YonghuEntity member = (YonghuEntity) request.getSession().getAttribute("member");
            
            kechengYuyueService.yuyueKecheng(kechengId, member.getId());
            request.setAttribute("msg", "预约成功");
        } catch (Exception e) {
            request.setAttribute("msg", "预约失败:" + e.getMessage());
        }
        return "redirect:/member/kecheng/list";
    }

    @PostMapping("/cancel")
    public String cancelYuyue(Integer yuyueId, HttpServletRequest request) {
        try {
            kechengYuyueService.cancelYuyue(yuyueId);
            request.setAttribute("msg", "取消成功");
        } catch (Exception e) {
            request.setAttribute("msg", "取消失败:" + e.getMessage());
        }
        return "redirect:/member/yuyue/list";
    }
}

2. 会员到期提醒模块(系统核心功能)

Service层实现:

@Service
public class MemberRemindServiceImpl implements MemberRemindService {
    
    @Autowired
    private YonghuMapper yonghuMapper;

    @Override
    @Scheduled(cron = "0 0 9 * * ?") // 每天上午9点执行
    public void checkMemberExpire() {
        // 查询7天内到期的会员
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DAY_OF_MONTH, 7);
        Date sevenDaysLater = calendar.getTime();
        
        List<YonghuEntity> expireMembers = yonghuMapper.selectList(
            new EntityWrapper<YonghuEntity>()
                .le("daoqi_time", sevenDaysLater)
                .gt("daoqi_time", new Date()) // 还未到期
                .eq("remind_sent", 0) // 未发送提醒
        );
        
        for (YonghuEntity member : expireMembers) {
            // 发送提醒(这里可以集成短信、邮件等)
            sendRemindMessage(member);
            
            // 标记已发送提醒
            member.setRemindSent(1);
            yonghuMapper.updateById(member);
        }
    }
    
    private void sendRemindMessage(YonghuEntity member) {
        // 实现提醒发送逻辑
        // 可以是系统消息、短信、邮件等
        System.out.println("提醒会员:" + member.getYonghuName() + 
                          ",您的会员将于" + member.getDaoqiTime() + "到期");
    }
}

3. 器材管理模块(管理员功能)

Service层实现:

@Service
public class QicaiServiceImpl implements QicaiService {
    
    @Autowired
    private QicaiMapper qicaiMapper;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        Page<QicaiEntity> page = new Page<>(
            Integer.parseInt(params.get("page").toString()),
            Integer.parseInt(params.get("limit").toString())
        );
        
        EntityWrapper<QicaiEntity> ew = new EntityWrapper<>();
        
        // 器材名称模糊查询
        if (params.get("qicaiName") != null) {
            ew.like("qicai_name", params.get("qicaiName").toString());
        }
        
        // 器材类型筛选
        if (params.get("qicaiTypes") != null) {
            ew.eq("qicai_types", params.get("qicaiTypes"));
        }
        
        // 状态筛选
        if (params.get("status") != null) {
            ew.eq("status", params.get("status"));
        }
        
        IPage<QicaiEntity> result = qicaiMapper.selectPage(page, ew);
        return new PageUtils(result);
    }

    @Override
    @Transactional
    public void updateQicaiStatus(Integer qicaiId, Integer status) {
        QicaiEntity qicai = new QicaiEntity();
        qicai.setId(qicaiId);
        qicai.setStatus(status);
        qicaiMapper.updateById(qicai);
    }
}

在这里插入图片描述 在这里插入图片描述 在这里插入图片描述

五、系统测试:确保业务流程可靠

曾经以为功能实现就完成了,结果测试时发现会员到期后还能预约课程,紧急加了会员状态校验。

1. 功能测试用例

课程预约测试:

测试场景操作步骤预期结果
会员已到期到期会员预约课程提示"会员已到期,请先续费"
课程已满员会员预约满员课程提示"课程已满员,无法预约"
时间冲突会员预约同一时段课程提示"该时段已预约其他课程"
正常预约会员预约有空位的课程提示"预约成功",课程人数+1

会员管理测试:

测试场景操作步骤预期结果
会员续费管理员为会员续费会员到期时间延长,状态恢复正常
到期提醒系统检查到期会员自动发送到期提醒消息

2. 业务规则测试

  • 预约限制:同一时段只能预约一门课程
  • 取消规则:课程开始前2小时内不可取消
  • 容量控制:课程报名人数不超过最大容量
  • 会员状态:到期会员无法预约课程

六、部署与演示准备

1. 数据库初始化脚本

-- 插入测试数据
INSERT INTO `yonghu` VALUES 
(1, '张三', '13800138000', '110101199001011234', '/images/user1.jpg', 'zhangsan@qq.com', 1, '2024-12-31', NOW(), NOW()),
(2, '李四', '13800138001', '110101199001011235', '/images/user2.jpg', 'lisi@qq.com', 2, '2024-06-30', NOW(), NOW());

INSERT INTO `jiaolian` VALUES 
(1, '王教练', '13800138002', '/images/coach1.jpg', 1, '国家级健身教练', '资深私教,擅长增肌减脂', NOW());

INSERT INTO `kecheng` VALUES 
(1, '瑜伽入门', 1, 1, 1, '2024-01-15 19:00:00', 60, 20, 0, '适合初学者的瑜伽课程', NOW());

2. 演示流程设计

按照真实业务流程演示:

  1. 会员注册登录→查看课程表→预约瑜伽课程
  2. 管理员登录→添加新课程→管理会员信息
  3. 会员取消预约→系统释放名额→其他会员预约

3. 答辩重点准备

  • 业务逻辑亮点:会员状态管理、课程容量控制、时间冲突检测
  • 技术实现亮点:Spring定时任务、事务管理、数据一致性
  • 系统特色:完整的健身业务流程、智能提醒功能

结语

基于Spring Boot的健身房管理系统毕设成功的关键在于:抓住会员管理核心,处理好课程预约业务,保证数据一致性。这套系统虽然业务逻辑相对复杂,但一旦掌握,无论是完成度还是技术含量都能得到导师认可。

记住:会员状态管理、课程预约逻辑、器材状态跟踪是三大得分点!需要完整源码、数据库脚本、部署文档的同学可以在评论区留言。

点赞收藏这篇,下次找流程不迷路~祝宝子们毕设顺利,轻松毕业!😘