ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

Spring Boot + Vue + MySQL 健身房管理系统源码实战:从本地跑通到部署避坑

Spring Boot + Vue + MySQL 健身房管理系统源码实战:从本地跑通到部署避坑 简介这是一套面向计算机专业毕业设计场景的健身房管理系统完整项目包采用Spring Boot后端、Vue前端与MySQL数据库的B/S架构适合正在准备毕设或需要Java全栈实战练手的学生与开发者。系统划分管理员、会员、员工三类角色覆盖个人中心、会员与员工管理、会员卡及类型管理、教练信息、解聘管理、健身项目与指导项目、健身器材和健身活动等模块业务链条完整具备一定实用价值。压缩包共444个文件约10.78MB其中122个Java源文件承载后端业务逻辑46个Vue组件构建前端页面另有SQL脚本、XML配置、JS与CSS资源及图片素材并附论文与部署说明便于快速理解项目结构与运行流程。目前已有86人学习下载。整体目录清晰、功能齐全可作为课程设计、毕设选题或全栈学习参考帮助读者掌握角色权限设计与前后端联调思路。1. 从一份健身房管理系统源码包说起Spring Boot Vue MySQL 到底能跑出什么健身房的日常运营里会员卡到期提醒、私教课时核销、器械巡检记录、前台收银对账这几件事几乎全靠人工表格在撑。一旦门店超过两家数据就开始打架会员在 A 店办的卡B 店查不到剩余次数私教课上了几节月底对账才发现教练和前台各记了一本账。基于 Spring Boot Vue MySQL 的健身房管理系统解决的正是这类「多门店、多角色、数据要实时对齐」的运营问题。它适合三类人想拿一个完整前后端分离项目练手的学生、需要给中小健身房做数字化改造的开发者、以及手上有一堆 Excel 想换成 Web 系统的门店老板。这份源码包把后端接口、前端页面、数据库脚本和部署说明打包在一起拿到手就能本地跑通改一改就能上线试运营。2. 技术选型与数据库设计为什么是 Spring Boot Vue MySQL 这套组合2.1 后端选 Spring Boot 而不是传统 SSM 的理由传统 SSMSpring SpringMVC MyBatis配置量大一个健身房系统光 XML 就能写上千行新人接手先要花两天理清 bean 依赖。Spring Boot 把内嵌 Tomcat、自动配置、起步依赖都封装好了一个application.yml就能管完数据源、端口、日志。对健身房这种业务逻辑不算复杂、但角色权限和定时任务比如会员卡到期扫描比较琐碎的场景Spring Boot 的开发效率优势很明显。具体到依赖核心是这几块!-- pom.xml 关键依赖 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId !-- REST 接口 -- /dependency dependency groupIdorg.mybatis.spring.boot/groupId artifactIdmybatis-spring-boot-starter/artifactId version2.3.1/version !-- 持久层写 SQL 灵活 -- /dependency dependency groupIdcom.mysql/groupId artifactIdmysql-connector-j/artifactId scoperuntime/scope !-- MySQL 驱动 -- /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-validation/artifactId !-- 参数校验 -- /dependency选 MyBatis 而不是 JPA是因为健身房系统里「按剩余次数排序会员」「统计某教练本月课时」这类查询手写 SQL 比 JPQL 更直观后期优化索引也方便。参数说明mybatis-spring-boot-starter的版本要和你 Spring Boot 版本匹配2.3.x 对应 Spring Boot 3.x用错版本启动会报NoClassDefFoundError。2.2 前端选 Vue 而不是 Thymeleaf 的考量健身房系统的用户分三类前台高频操作要快、教练看课表要清晰、老板看报表要图表。这三类需求用服务端渲染的 Thymeleaf 做每次操作都整页刷新前台收银时体验很差。Vue 做前后端分离页面局部更新配合 Element Plus 的表格和表单组件开发速度快后期加个 ECharts 营收图表也顺手。前端初始化命令# 用 Vite 创建 Vue 3 项目比 vue-cli 快很多 npm create vitelatest gym-frontend -- --template vue cd gym-frontend npm install npm install element-plus axios vue-router pinia echarts npm run dev逻辑说明Vite 的冷启动在秒级改代码热更新几乎无感。element-plus提供现成的表格、弹窗、日期选择器健身房系统里会员登记、课程排期这些表单直接套。pinia管登录态和门店切换vue-router管路由权限。参数上注意Vue 3 要用 Element Plus 的 2.x 版本Vue 2 用 1.x混用会报组件注册失败。2.3 数据库表设计的四个核心实体健身房系统的表不用多但几张核心表的关系要理清。下面是我一般会用的最小可用表结构表名关键字段说明memberid, name, phone, card_type, balance, expire_date, store_id会员主表store_id 区分门店courseid, coach_id, name, capacity, start_time, duration课程表capacity 控制人数上限bookingid, member_id, course_id, status, create_time预约记录status 标记已约/已到/爽约coachid, name, phone, store_id, hourly_rate教练表hourly_rate 用于课时费结算建表时两个细节容易翻车一是phone字段加唯一索引防止同一手机号重复办卡二是booking表对(member_id, course_id)加联合唯一索引避免同一会员重复预约同一节课。MySQL 8.0 建表语句CREATE TABLE member ( id BIGINT NOT NULL AUTO_INCREMENT, name VARCHAR(32) NOT NULL, phone VARCHAR(20) NOT NULL, card_type TINYINT DEFAULT 1 COMMENT 1月卡 2季卡 3年卡, balance DECIMAL(10,2) DEFAULT 0.00, expire_date DATE, store_id INT NOT NULL, PRIMARY KEY (id), UNIQUE KEY uk_phone (phone), KEY idx_store (store_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;utf8mb4是必须的会员姓名里偶尔有生僻字用utf8会插入失败。DECIMAL(10,2)存金额别用FLOAT否则对账时会出现 0.01 的误差。3. 本地跑通的最小路径从 MySQL 建库到前后端联调3.1 MySQL 安装与建库的三个关键动作Windows 上装 MySQL 8.0下载地址去官网找mysql-installer-community版本。安装时选Custom把MySQL Server和MySQL Workbench勾上。配置阶段注意认证方式选Use Strong Password Encryption端口保持 3306root 密码设一个自己记得住的。装完后建库CREATE DATABASE gym_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; CREATE USER gym_user% IDENTIFIED BY Gym2024; GRANT ALL PRIVILEGES ON gym_db.* TO gym_user%; FLUSH PRIVILEGES;逻辑说明单独建一个gym_user而不是直接用 root是为了部署到服务器时权限可控。%允许远程连接本地开发也可以改成localhost更安全。执行完用mysql -u gym_user -p登录验证一下能进就说明权限没问题。3.2 Spring Boot 后端配置与启动拿到源码后先改application.ymlserver: port: 8080 # 如果被占用改成 8081 spring: datasource: url: jdbc:mysql://localhost:3306/gym_db?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: gym_user password: Gym2024 driver-class-name: com.mysql.cj.jdbc.Driver mybatis: mapper-locations: classpath:mapper/*.xml type-aliases-package: com.gym.entity参数说明serverTimezoneAsia/Shanghai不加会报时区错误这是 MySQL 8.0 的经典坑。mapper-locations指向 XML 映射文件如果启动报Invalid bound statement八成是这里路径写错了。改完用 IDEA 打开项目等 Maven 依赖下载完直接运行GymApplication主类。控制台出现Started GymApplication in x seconds就说明后端起来了。3.3 Vue 前端启动与接口联调前端项目里找到src/utils/request.js改 baseURLimport axios from axios const request axios.create({ baseURL: http://localhost:8080/api, // 后端接口前缀 timeout: 10000 }) // 请求拦截器带上 token request.interceptors.request.use(config { const token localStorage.getItem(token) if (token) { config.headers.Authorization Bearer ${token} } return config }) export default request逻辑说明拦截器统一加 token避免每个请求手动写。timeout设 10 秒健身房系统里报表查询可能稍慢设太短会误报超时。改完执行npm run dev浏览器打开http://localhost:5173用默认账号一般是 admin/123456登录。如果登录报 404检查后端接口路径是不是/api/login前端 baseURL 和后端RequestMapping要对上。3.4 前后端打包部署到一台服务器开发跑通后部署是另一道坎。后端打包mvn clean package -DskipTests # 生成 target/gym-0.0.1-SNAPSHOT.jar java -jar gym-0.0.1-SNAPSHOT.jar --spring.profiles.activeprod前端打包npm run build # 生成 dist 目录把里面的文件拷到 Nginx 的 html 目录Nginx 配置里加一段反向代理把/api转发到 8080location /api/ { proxy_pass http://127.0.0.1:8080/api/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; }这样前端静态资源和后端接口同域省去跨域配置。注意proxy_pass末尾的斜杠带斜杠和不带斜杠转发路径不一样这是 Nginx 最常见的翻车点之一。4. 避坑与排查健身房系统落地时最容易翻车的五个地方4.1 会员卡到期提醒不触发现象定时任务配了但会员到期前三天没收到任何提醒。原因Spring Boot 的Scheduled默认单线程如果前一个任务卡住后面的不执行。解决在配置类里加线程池Configuration EnableScheduling public class ScheduleConfig implements SchedulingConfigurer { Override public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { taskRegistrar.setScheduler(Executors.newScheduledThreadPool(5)); } }同时检查 cron 表达式0 0 9 * * ?是每天早九点别写成0 0 9 * * *后者在 Quartz 里不合法。4.2 预约课程时超卖现象课程容量 10 人结果约进来 12 个。原因并发请求下先查后插两个请求同时查到剩余 1 个名额。解决在booking表加唯一索引不够要用数据库行锁或乐观锁。简单做法是在course表加booked_count字段更新时带条件UPDATE course SET booked_count booked_count 1 WHERE id ? AND booked_count capacity;判断受影响行数为 0 就说明满了返回「课程已满」。4.3 前端打包后刷新页面 404现象npm run dev正常打包放 Nginx 后在/member/list页面按 F5 就 404。原因Vue Router 的 history 模式需要服务端把所有路径回退到index.html。解决Nginx 加location / { try_files $uri $uri/ /index.html; }如果用 hash 模式URL 带#就不会有这个问题但 URL 不好看我一般还是用 history 模式加这行配置。4.4 MySQL 连接数不够用现象系统跑几天后报Too many connections。原因连接池配置的max-active太大或者代码里有连接没关闭。解决application.yml里加 HikariCP 配置spring: datasource: hikari: maximum-pool-size: 20 minimum-idle: 5 connection-timeout: 3000020 个连接对中小健身房足够设太大反而拖垮数据库。同时检查 MyBatis 的SqlSession有没有手动关闭用Mapper注解的接口由 Spring 管理一般不用管。4.5 跨域问题在开发环境反复出现现象前端 5173 端口调后端 8080浏览器控制台报 CORS 错误。原因开发时前后端不同源。解决后端加全局跨域配置Configuration public class CorsConfig implements WebMvcConfigurer { Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(/api/**) .allowedOriginPatterns(*) .allowedMethods(GET, POST, PUT, DELETE) .allowCredentials(true) .maxAge(3600); } }注意allowedOriginPatterns和allowedOrigins的区别前者支持通配符且允许携带凭证后者在allowCredentials(true)时不能用*。生产环境把*换成具体域名。5. 从能跑到好用三个让健身房系统真正落地的进阶技巧5.1 用 ECharts 做营收看板老板一眼看懂健身房老板不关心代码只关心「这个月卖了多少卡、私教课收入多少、哪个教练课时最多」。在 Vue 里用 ECharts 画三个图折线图看每日营收趋势饼图看卡类型占比柱状图看教练课时排名。核心代码import * as echarts from echarts // 营收趋势折线图 const chart echarts.init(document.getElementById(revenueChart)) chart.setOption({ xAxis: { type: category, data: dateList }, // 后端返回的日期数组 yAxis: { type: value }, series: [{ data: revenueList, type: line, smooth: true, areaStyle: { color: rgba(64,158,255,0.2) } }] })数据从后端/api/report/revenue?storeId1month2024-06拿SQL 用DATE(create_time)分组求和。注意 ECharts 实例要在onMounted里初始化否则 DOM 还没渲染完图表是空白的。5.2 用 Spring Boot Admin 监控接口健康度系统上线后最怕的是接口悄悄挂了没人知道。加spring-boot-starter-actuator和 Spring Boot Admin能实时看堆内存、线程数、接口响应时间。配置management: endpoints: web: exposure: include: health,info,metrics endpoint: health: show-details: always然后起一个 Admin Server 项目把健身房系统的地址注册进去。这样每天早上打开 Admin 页面扫一眼有异常指标提前处理比等前台打电话说「系统卡了」要从容得多。5.3 会员数据导出与备份的稳妥做法健身房最怕数据丢会员资料和消费记录丢了就是真金白银的损失。两个习惯一是 MySQL 每天凌晨自动备份用mysqldump加 crontab# 每天凌晨 2 点备份保留最近 7 天 0 2 * * * mysqldump -u gym_user -pGym2024 gym_db /backup/gym_$(date \%Y\%m\%d).sql find /backup -name gym_*.sql -mtime 7 -delete二是给老板做一个「导出会员 Excel」的按钮用 EasyExcel 写别用 POI 的HSSFWorkbook数据量一大就 OOM。导出时注意脱敏手机号中间四位打码这是合规的基本要求。我自己踩过最深的坑是早期图省事把会员余额直接存在member表里后来做退款和赠送金额时发现根本对不上账。后来改成独立的balance_log流水表每一笔充值、消费、退款都记一条余额由流水汇总得出对账再也没出过问题。做这类系统宁可多一张流水表也别在余额字段上省事。希望帮到你。本文还有配套的精品资源点击获取
返回列表