☰
SpringBoot+Vue+MySQL体育馆管理系统源码解析与部署实战
2026/10/21 12:33:41 网站建设 项目流程

这套体育馆管理系统源码,名字里写得很清楚:SpringBoot 后端 + Vue 前端 + MySQL 数据库,并且特意标注了“可直接运行”。我拿到这套项目后,第一反应是终于遇到一个不含糊的实战项目了。很多同学毕设或者小团队内部系统,最怕的就是源码下载下来跑不起来,环境缺这缺那,光启动就要折腾两天。这套系统我之前完整部署过一次,整体结构常规但不平庸,功能覆盖了体育馆常见的场地预约、会员管理、教练排班、订单统计等场景,非常适合拿来学习前后端分离架构,或者直接改改用了做课程设计。

这篇文章我不会只把启动命令复述一遍,而是把整个项目从设计思路、后端核心逻辑、前端页面实现、到本地部署的每个关键环节都拆开来讲。你跟着操作一遍,不仅能跑起来,还能搞清楚每个表、每个接口、每个页面之间是怎么配合的,遇到报错也知道去哪查。

1. 项目整体设计与技术选型思路

1.1 海滨体育馆到底需要一个什么样的系统

先别急着敲代码,我们先想想业务场景。一家体育馆,日常要管理的不只是“订个场”这么简单。客户需要线上查看空闲时段、预约羽毛球馆、篮球场或游泳馆,管理员要能设置场馆开放时间、管理会员、处理退款、统计每日营业额。如果只用Excel表登记,数据一多就会乱,预约冲突、账目不清几乎无法避免。

所以这套系统的核心价值就是:把场地资源、会员信息、预约订单、收费记录统一放到一个可视化系统里管理。我拆开源码看过,它的主要模块包括:

  • 场馆管理:维护场馆名称、类型、开放时段、收费标准
  • 预约管理:用户选择场馆和时段下单,后台生成订单
  • 会员管理:记录会员卡类型、余额、有效期,支持会员价
  • 订单财务管理:记录实收金额、支付方式、退款状态
  • 系统用户管理:区分管理员和普通员工,不同角色不同权限

这样的结构不算复杂,但对一个中小型体育馆来说,已经覆盖了日常运营80%以上的场景。你如果拿它做毕设,答辩时能把每个模块说清楚,老师很难挑出大毛病。

1.2 为什么选 SpringBoot + Vue + MySQL 这套组合

这个项目的技术选型很典型,也很适合多数人学习。SpringBoot负责后端接口开发,它简化了 Spring 框架的配置,内置 Tomcat,一个java -jar就能启动服务;Vue负责前端页面,组件化开发,配合 Element UI 这类组件库可以快速搭建管理后台;MySQL存数据,开源稳定,学校和企业都用它,而且招聘市场上这套组合的需求量一直很大。

有人可能会问:为什么不选 Spring Cloud、微服务、Redis 这些东西?说实话,对一个体育馆管理系统来说,微服务完全是过度设计。单体应用启动快、部署简单、排错直观,数据和业务都在一个事务里,逻辑清晰。学习阶段把单体做扎实,比硬上一堆中间件有用得多。

另外,我注意到这套源码的前后端是分离的,开发环境里后端跑 8080 端口,前端跑 8081 端口,前面通过代理转发请求。这种模式下,前端和后端可以并行开发,你单独改页面不需要重启 Java 服务,单独调接口也不需要重新编译前端,开发体验比老式 JSP 模板舒服太多。

1.3 整体功能模块与数据流转关系

从源码目录结构可以很容易看出项目的分层思路:

  • 后端按 Controller -> Service -> Mapper 三层分包,控制器只接收参数和返回结果,业务逻辑写在 Service,数据库操作用 MyBatis-Plus 或 JPA 的 Mapper 完成
  • 前端按页面视图划分,通常是src/views/admin、src/views/user这种结构,路由配置在router/index.js
  • 数据库包含用户表、场馆表、预约单表、订单表、会员卡表等

数据流转也很直接:用户在 Vue 页面上点击“确认预约”,前端把选的场馆、时间段、价格组装成一个 JSON,通过 axios 发送 POST 请求到后端/api/order;后端先验证该时段是否已被占用,再判断用户余额或在线支付的金额是否足够,最后写库生成订单,把状态返回给前端。这一条线走通,系统的核心闭环就成立了。

提示:建议拿到源码后先从数据库脚本看起。.sql文件里表结构的注释往往比代码更能帮你理解整个业务模型。

2. 后端核心实现与关键细节

2.1 环境准备与项目初始化

我这台机器是 Windows 11,部署这套系统用到的工具版本如下,你可以直接参照:

  • JDK 1.8 或 JDK 11(我用的是 JDK 1.8,稳定)
  • Maven 3.6.3
  • MySQL 5.7 / 8.0
  • Node.js 14.17.0
  • IDEA 或 Eclipse

后端工程导入 IDEA 后,先等 Maven 把依赖下完。然后找到application.yml或application.properties,核心配置就是数据库连接:

server: port: 8080 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/sports_center?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai username: root password: 123456 jpa: database-platform: org.hibernate.dialect.MySQL5InnoDBDialect hibernate: ddl-auto: none show-sql: true

注意 MySQL 8.0 必须加serverTimezone,否则报时区错误。ddl-auto设为none表示不用框架自动建表,你手动执行项目里的 SQL 脚本即可,这是很多项目能“开箱可运行”的前提。

2.2 数据库表设计与实体映射的讲究

打开数据库脚本,核心表设计我总结一下:

表名用途关键字段
user后台用户/会员账户username,password,role,status
venue体育馆场地name,type,price_per_hour,open_time,close_time
reservation预约记录user_id,venue_id,date,start_time,end_time,status
order订单流水order_no,amount,pay_type,create_time

密码字段记得不是明文。这个项目里用了 MD5 加盐或 BCrypt,可以直接在UserServiceImpl中看到加密逻辑。如果想用http.antMatchers("/api/**")做接口权限,确实要保证前端传过来的密码加密方式一致,否则登录接口会一直报“用户名或密码错误”。

MyBatis-Plus 的实体类一般用@TableName("reservation")注解映射表名,字段用驼峰命名,开启map-underscore-to-camel-case后,start_time能自动映射成startTime,非常省事。

2.3 权限设计与登录鉴权实现

我不知道你有没有遇到过这种情况:明明功能都写完了,但用户能直接调接口改别人订单。这个项目里用了 JWT(JSON Web Token)做身份识别,我用下来体验是:简单够用,比 Session 合适前后端分离。

登录流程是:

  1. 前端调用/api/user/login,传username和password
  2. 后端比对成功,生成一个 JWT 令牌,把用户 ID 和角色塞进去,返回给前端
  3. 前端把 Token 存在localStorage,每次发请求在拦截器中加Authorization: Bearer <token>
  4. 后端的拦截器解析 Token,拿着用户信息放行或拒绝请求

我在测试时故意用一个普通用户 Token 去调管理员接口,结果返回 403。这说明权限确实生效了。

如果你改这套系统,建议把角色判断从if ("admin".equals(role))换成自定义注解@PreAuthorize,代码会干净很多,也更容易维护。

2.4 场馆预定与订单状态的业务逻辑

预定功能是这个系统的灵魂。后端的实现逻辑大致是:

  • 前端传venueId、预约日期、开始小时和结束小时
  • 后端先查询该场馆在指定日期当前时段的预约记录:
    QueryWrapper<Reservation> wrapper = new QueryWrapper<>(); wrapper.eq("venue_id", venueId) .eq("date", date) .eq("status", 1) .lt("start_time", endTime) .gt("end_time", startTime); Integer count = reservationMapper.selectCount(wrapper); if (count > 0) { return Result.error("该时段已被预约"); }
  • 没有冲突,就生成订单并扣除用户余额或记录在线支付

这里判断时间段是否重叠的 SQL 条件值得你花时间理解:新预约开始小于已有预约结束 且 新预约结束大于已有预约开始。这两个条件同时满足,说明时间有重叠。这比单纯比较startTime == startTime科学得多,也是面试里经常问的一道编程题。

如果订单状态有“已取消”字段,删除时最好用逻辑删除,也就是把status改成 0,而不是物理 DELETE。这样统计报表才能追回历史取消记录,也不容易把用户钱包金额算错。

3. 前端 Vue 页面的落地要点

3.1 Vue 项目结构与路由设计

前端工程目录结构通常很清晰:

src ├─ api │ ├─ login.js │ └─ reservation.js ├─ assets ├─ components ├─ router │ └─ index.js ├─ store │ └─ module ├─ views │ ├─ Login.vue │ ├─ Dashboard.vue │ ├─ venue │ │ └─ VenueList.vue │ ├─ reservation │ │ └─ ReservationCreate.vue │ └─ admin └─ main.js

路由设计里,我比较关注的是路由守卫。在router/index.js中:

router.beforeEach((to, from, next) => { const token = localStorage.getItem("token"); if (to.path !== "/login" && !token) { next("/login"); } else { next(); } })

这能保证用户在未登录状态下无法直接访问后台页面。你搜索源码时如果发现没有这行逻辑,建议补上,否则系统登录权限形同虚设。

3.2 axios 封装与接口调用的统一处理

前端所有请求应该经过一个统一的request.js封装,而不是每个页面里写一堆axios.get。这样做的理由很简单:你可以统一处理令牌、统一报错提示、统一打印日志。

我比较喜欢这个项目里的封装方式:

import axios from "axios"; const service = axios.create({ baseURL: process.env.VUE_APP_BASE_URL, timeout: 10000 }); service.interceptors.request.use(config => { const token = localStorage.getItem("token"); if (token) { config.headers["Authorization"] = "Bearer " + token; } return config; }); service.interceptors.response.use( response => response.data, error => { if (error.response.status === 401) { localStorage.clear(); location.href = "/login"; } return Promise.reject(error); } ); export default service;

这样一旦 Token 过期,前端自动跳回登录页,用户不会看到一堆奇怪的报错。你在部署时如果发现有跨域问题,多半是后端的跨域配置没打开或者代理没配对。

3.3 核心页面组件的实现细节

预约场馆页面通常用到 Element UI 的日期选择器和时间选择器。用户选中某个场地,页面上会实时显示当前时段价格:

<el-date-picker v-model="reservation.date" type="date" placeholder="选择日期" :disabled-date="disabledDate" > </el-date-picker>

disabledDate可以用来禁掉过去日期,避免用户填昨天的订单。

场地卡片列表里,通常有一个“查看空闲时间”的功能。前端拿到场馆的预约列表后,用数组生成当天从开门到关门的连续时段,再把已被预约的时段标记为灰色,之后用户只能选择绿色时段。这类交互写起来不难,但比后端接口更直观,适合新手练习。

注意:前端页面提交到后端的金额不要只靠前端计算。所有价格校验必须在后端重新做一遍,因为用户可以改请求参数。这种“前端显示、后端控制”的原则,前后端分离项目里一定要记住。

4. 本地部署与直接运行指南

4.1 你需要在电脑上装哪些工具

这套系统实现“直接运行”的前提是环境齐全。我把清单列出,少了哪个赶紧补:

  1. JDK 8 以上,配置好JAVA_HOME
  2. Maven,配置好本地仓库路径,方便下依赖
  3. MySQL 5.7+,并创建数据库
  4. Node.js 14 以上,自带 npm 包管理工具
  5. 一个趁手的 IDE:后端用 IDEA,前端用 VSCode

上面少了任意一个,项目都不可能真正跑起来。所谓“可直接运行”,指的是一套完整代码加配置,而不是一个被剪裁的演示片段。

4.2 数据库导入与后端启动步骤

先在 MySQL 里建库:

CREATE DATABASE sports_center DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;

然后使用命令导入源码提供的 SQL 文件:

mysql -u root -p sports_center < sports_center.sql

导入完成后检查一下reservation、order表几条数据是否正常。

接着用 IDEA 打开后端目录,等待 Maven 同步完成,在运行配置中选主类SportsCenterApplication,点 Run。看到类似下面的日志,说明后端已经成功启动:

Tomcat started on port(s): 8080 (http) with context path ''

4.3 Vue 前端安装依赖与启动调试

打开前端目录,终端里执行:

npm install

这一步会拉取所有依赖。如果 npm 源慢,可以切到国内镜像:

npm config set registry https://registry.npmmirror.com

安装完成后运行:

npm run dev

看到Local: http://localhost:8081就说明前端起来了。这时浏览器访问http://localhost:8081,登录页出现,说明前后端已经联调成功。

4.4 常见启动报错排查表

我把实际运行中别人经常遇到的几个问题整理成表,按这个查,能省很多时间:

报错信息可能原因解决方式
Access denied for user 'root'@'localhost'数据库密码填错修改application.yml里的password
Unknown database 'sports_center'没建库或库名不对先执行CREATE DATABASE
Port 8080 was already in use.端口被占用netstat -ano查进程并结束,或改server.port
Error: Cannot find module 'node-sass'前端依赖没装全重新npm install,或升级为sass
Network Error前端代理没配置检查vue.config.js里proxy是否指向 8080

提示:前端请求跨域还可能是后端没开跨域配置。SpringBoot 中可以加一个配置类,实现WebMvcConfigurer重写addCorsMappings,或者直接用@CrossOrigin注解。

5. 实操踩坑记录与优化建议

5.1 我遇到的五个实际坑

第一个坑,数据库时区。第一次我用的 MySQL 8.0,连接 URL 没写serverTimezone,启动直接报The server time zone value 'Öйú±ê׼ʱ¼ä'。这属于基础配置问题,但足够卡新手半天。

第二个坑,前端 Node 版本太高。原本用的 Node 17 跑 Vue2 项目,编译报错内容很奇怪,最后把 Node 降到 14,问题消失。

第三个坑,JWT 密钥每次重启后,旧的 Token 全部失效。这个项目里 JWT 密钥是写死的,重启后应该还有效;如果写在随机数里,用户会被迫重新登录,注意这细微差别。

第四个坑,预约时间冲突判断不严谨。源码最初只判断了完全相同的开始时间,到现在我改成了交叉区间判断。不加这个优化,用户可以把同一场地不同时段都占满,也会出现真实业务中“从 10 点到 12 点和从 11 点到 13 点撞车”的情况。

第五个坑,前端页面刷新后白屏。原因大多是 history 模式的路由在 nginx 没配置try_files。本地 dev 不会遇到,打包部署时就需要加一句:

location / { try_files $uri $uri/ /index.html; }

5.2 数据库连接池与字段类型的优化

标题里说“可直接运行”,但真要投入生产,有几个点要改:

  • 连接池默认配置可能用 HikariCP,这是 SpringBoot 2 系列的默认选项,并发不高没什么问题。要把maximum-pool-size调到与业务峰值匹配
  • 订单金额字段用decimal(10,2)而不是double,避免浮点误差。如果你翻 SQL 发现有人用了float,建议马上改掉
  • 时间字段建议用datetime存完整时间,而不是把日期和时间拆成两个varchar。否则你统计“某月销售额”时,SQL 写起来要人命

5.3 这套系统还能往哪些方向扩展

如果你不满足于原样运行,可以考虑加这么几个功能:

  • 短信/邮件预约提醒:在订单生成后调一个异步任务,提前一天发送提醒,体验会好很多
  • 微信小程序端:后端接口基本都是 JSON,只要再做一套小程序页面,就能打通移动端预约
  • 数据统计可视化:对接 ECharts,做场馆利用率、营收趋势、峰值时段分析
  • 多租户模式:如果要把系统卖给不同体育馆,可以给场馆表加tenant_id,实现一套代码多馆共用

这些扩展方向里,最简单的入门改造是加 ECharts 图表,因为数据表已经齐全,只要写几个聚合查询接口就行。我曾经花一个下午,给这套系统加了三张报表,答辩或演示时效果提升非常明显。

我个人在实际操作中的体会是:这套“海滨体育馆管理系统”的价值不在于代码多么华丽,而在于它是一条完整的前后端分离学习链路。你把它跑起来,是第一步;把链路里每一步的“为什么”弄懂,才是真正的收获。网上能下载的源码很多,但真正变成自己的,一定是你亲手排查过报错、动手改过业务逻辑的那些代码。先用起来,再改起来,这套系统就能成为你能力水平的一块不错的垫脚石。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询