ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Spring Boot赛事管理系统设计与实战:从赛程编排到排名计算

Spring Boot赛事管理系统设计与实战:从赛程编排到排名计算 不废话直接说项目。这是一套基于 Spring Boot 的乒乓球赛事管理系统编号 27374属于典型的计算机毕业设计选题。整套系统围绕赛事从发布到结束这条主线展开管理员创建比赛、运动员注册报名、系统自动编排赛程、裁判录入比分、最后自动计算积分和排名。对于正在找毕设题目或者想快速落地一套 JavaWeb 项目的同学来说这个题目的业务边界清晰、技术栈主流、工作量适中是很容易出成果也容易讲清楚的那一类选题。我平时带学生做毕设最怕的就是题目太虚。什么基于大数据的某某平台智能化的某某系统听着高级实际上做不出来答辩也讲不清楚。乒乓球赛事管理系统这种题目的好处在于——它是一门真实存在的业务规则清楚11分制、7局4胜、单循环、淘汰赛这些有确切定义用户角色明确管理员、运动员、裁判流程完整报名到排名所以数据库表结构、接口设计、前端页面都有标准答案可循不需要你拍脑袋编需求。1. 这个项目到底在做什么1.1 毕业设计选型的门道先聊聊为什么每年有大量毕业生选 Spring Boot 做毕设。答案是生态成熟、学习曲线平缓、就业面试用得上。Spring Boot 最核心的优势是把过去 SSM 框架时代繁琐的 XML 配置、Bean 组装、依赖管理这些都替你处理掉了你只需要关注业务逻辑本身。尤其对于毕设这种场景你有两三个月时间还得应付论文、答辩、查重不可能把大量时间花在环境搭建和框架配置上。我用这套系统带过几届学生平均下来一个人从拿到需求到跑通全部流程大概四到六周。这还是在边上课边做的前提下。如果你基本功扎实一些三周连论文带代码全部搞定也不是不可能。再说为什么选乒乓球这个具体运动。你在简历上写赛事管理系统其实不太显眼但写乒乓球赛事管理系统会具体很多面试官能更快理解你做了什么。而且乒乓球有非常标准的赛制规则这让你在论文里能写出有逻辑的东西比如单循环赛和淘汰赛的算法对比这在计算机专业里对应的是图结构和二叉树有理论可讲比普通增删改查更有深度。1.2 乒乓球赛事管理的业务全景从一个实际的比赛场景出发某个学校要办一场乒乓球比赛运动员报名有男单、女单、混双这些项目报名的人确定了之后赛事管理人员需要告诉每个人——你分在哪个组、跟谁打、几号场地、几点比、赢了积几分最后还要统计出谁是冠军、排名怎么排。这套系统要做的就是把这些线下事务搬到线上。我给学生规划的功能全景如下第一个模块是系统管理。管理员登录、修改密码、管理账号状态、给用户分配角色。这是所有系统的地基没有权限控制后面的数据就是一团乱麻。第二个模块是基础数据管理。包括运动员信息维护、裁判信息维护、场地信息维护。运动员的信息不仅仅是姓名手机号还应该包括所属单位或俱乐部、历史积分等基础信息这些数据在后续的报名和种子选手设定中会用到。第三个模块是赛事管理。创建一个比赛设置比赛名称、举办时间、报名开始截止时间、比赛项目男单、女单、双打等、赛制小组循环还是直接淘汰、积分规则这些参数。一个系统里可以同时存在多个比赛比如春季赛、秋季赛、校园杯、师生友谊赛。第四个模块是报名模块。运动员在系统里看到当前开放报名的赛事选择自己要参加的项目提交报名管理员可以审核报名资格、取消不符合条件的报名记录。第五个模块是赛程编排模块。这是整个系统的核心亮点。系统根据报名的运动员数量和赛制规则自动生成对阵表。小组赛用循环赛算法保证每个人都碰面淘汰赛用晋级树保证比赛逐步推进。第六个模块是比分管理和排名模块。裁判录入每场比赛的比分系统根据胜负自动计算小组积分、更新排名淘汰赛晋级下一轮的数据也会自动推进。到了这一步整个赛前-赛中-赛后的闭环就通了。这也是论文里业务流程设计这一章的最好素材。2. 从零搭系统架构设计与技术选型2.1 这套系统用什么技术栈最稳后端在网络上的主流做法是 Spring Boot MyBatis Plus MySQL前端学得快的用 Vue ElementUI不想做前后端分离的也可以用 Thymeleaf 直接套页面。我个人的建议是如果你对自己前端水平有信心用 Vue 做前后端分离这个是当前企业的主流做法答辩时也更有东西讲如果时间确实紧那就直接用 Thymeleaf少一套接口联调的工作量。Spring Boot 版本建议用 2.7.x这个版本既不会太老又不是太激进。Spring Boot 3.0 之后包名从 javax 改成了 jakarta网上很多老教程直接废掉了遇到报错排查起来很费时间。尤其做毕设时间是硬约束别在这种地方给自己挖坑。MyBatis Plus 是 MyBatis 的增强工具最大的好处是单表操作的 CRUD 不用写 XML。内置的 BaseMapper 帮你把增删改查都封装好了你只需要写业务逻辑和复杂查询的 SQL。这对毕设来说省了很大一部分体力活。有学生会问为什么不用 JPA我只能说 JPA 的上限高但入门曲线陡而且 SQL 调优不好讲。MyBatis Plus 生成的 SQL 你能看得见摸得着答辩的时候老师问一个问题你就能把对应的 SQL 写出来这是很加分的。数据库方面 MySQL 5.7 或者 8.0 都行建议 8.0。注意 8.0 的驱动类名变成了com.mysql.cj.jdbc.Driver配置时别写错。2.2 数据库表结构设计这是拿分大项很多学生做毕设一上来就写代码这是本末倒置。数据库表设计直接决定了你后面的代码好写不好写也是论文里的核心章节。我这套系统规划了七张核心表下面逐个拆解。sys_user 是用户表也就是登录账号表。字段包括 id、username、password、role、status、create_time 等。role 字段用来区分管理员、运动员、裁判这三种角色。password 用的是 BCrypt 加密存储这个点要在论文里写清楚因为很多评委会关注密码的安全性。player 是运动员信息表。字段包括 id、user_id、real_name、gender、phone、club所属单位、level运动等级或历史积分、create_time 等。这里把 user_id 关联到 sys_user一个登录账号对应一份运动员资料。competition 是赛事表。字段包括 id、name、description、start_time、end_time、registration_start、registration_end、status、max_player报名人数上限、rule_type赛制循环/淘汰等。status 字段是关键它的取值变化贯穿整个流程草稿、待审核、报名中、比赛中、已结束。比赛项目表 competition_event 用来记录每个赛事下面有哪些小项。如果一场赛事同时有男单、女单、混双三个项目就可以在这里存三条记录。字段包括 id、competition_id、event_name、gender_type、max_players、current_players 等。registration 是报名表。每一条报名记录代表一个运动员在某赛事某项目中报名参赛。字段包括 id、competition_id、event_id、player_id、status、create_time。status 表示待审核、已通过、已拒绝。schedule 是赛程表。字段包括 id、competition_id、event_id、round、group_no、player_a_id、player_b_id、court、scheduled_time、status、result_id。这一条就能记录一场比赛是谁打谁、在哪个场地、几点打、什么阶段、结果关联到哪条记录。match_result 是比赛结果表。字段包括 id、schedule_id、winner_id、loser_id、score_a、score_b、score_detail保存每局的小分比如11:7,9:11,11:5,11:8、duration_minutes、create_time。这里面 score_detail 建议用字符串存小分明细方便回溯比赛过程。这七张表的字段类型我建议你自己多琢磨两遍再敲 SQL尤其是时间类型统一用 datetime金额和比分统一用数字类型不要出现同一个含义的字段有的叫 create_time 有的叫 create_date 这种低级问题。表设计的一致性在评阅阶段会被仔细看。2.3 前端框架Vue 还是服务端渲染我前面提到了两种前端方案。这里展开说下取舍。如果你选 Vue ElementUI 的前后端分离方案项目目录会分成 springboot 后端工程和 vue 前端工程两个。后端只提供 Restful API返回 JSON 数据前端负责页面展示和交互。开发的时候需要启动两个服务部署的时候前端的 dist 静态文件可以由 Nginx 托管也可以把打包后的文件放到 Spring Boot 的 static 目录下做到单进程部署。第二种是用 Thymeleaf。它运行在服务端页面里的数据是通过模板语法直接渲染的。好处是不用跨域、不用考虑 Token 传递开发调试更直接适合时间紧张的学生。但说句实话我建议有点追求的同学还是走 Vue 路线。因为毕设答辩时评委大概率会问你前后端分离和不分离的区别Vue 在项目中是怎么和 Spring Boot 通信的这些内容在论文里可以写在回答中也能体现你对当前主流开发模式的掌握。基于这个考虑下面的实操部分我统一按前后端分离的架构来讲。3. 核心功能模块的拆解与实现3.1 用户与权限角色权限是怎么控制的先处理最基础的用户登录和权限。用户表里定义了三种角色后端通过 Spring Security 或者一个简单的拦截器来做权限控制。Spring Security 功能强但配置复杂毕设里如果要用它至少得把过滤器链、UserDetailsService、JWT 无状态认证这几个概念搞明白否则只看网上复制来的配置代码很容易在答辩时被追问到卡壳。一个折中的做法是使用拦截器 Token 的方式。用户登录成功后后端生成一个 Token 返回给前端前端在后续请求的 Header 里带上 Token。后端写一个 WebMvcConfigurer 拦截器对所有非登录接口校验 Token解析用户信息再判断当前操作是否有权限。这种方式代码量少、逻辑直观适合毕设。注解式权限控制也不错。自定义一个RequireRole注解和对应的拦截器在 Controller 方法上标注RequireRole(ADMIN)代码的可读性会提升不少。我在给学生做代码评审时特别喜欢这个设计因为这种主动设计比把权限判断写死在每个方法里要高级得多论文的技术亮点也能多一条。需要注意 Token 的密钥和有效期。用io.jsonwebtoken的 JWT 库时密钥至少 32 字符过期时间一般设 2 小时。Token 里只放用户 id 和角色不要放密码等敏感信息。3.2 赛事与报名赛程怎么开张赛事模块的核心操作是创建比赛。管理员在前端填表提交到后端的/competition/create接口服务端先生成一条 competition 记录然后再往 competition_event 中插入该赛事对应的比赛项目。这两个操作的关联性要求事务控制用Transactional注解可以保证两个插入要么同时成功要么同时失败这是很经典的一个考点。报名模块的核心接口是提交报名和审核报名。运动员提交报名的时候后端要校验几个条件赛事是否处于报名状态、报名是否截止、当前赛事该项目名额是否已满、该运动员是否已经报过这个项目。这些判断用一个 Service 层的方法串起来不要散落在 Controller 里Controller 保持薄薄一层只处理参数和返回结果这是面试和答辩的加分项。报名结束后管理员执行关闭报名操作系统检查完所有报名记录后生成该项目的参赛名单。此时如果某个运动员没有审核通过就不会进入接下来的赛程编排环节。3.3 赛程编排循环赛和淘汰赛怎么落地赛程编排是这套系统最值得写进论文的部分也是答辩时最能展示亮点的地方。先说小组循环赛。循环赛的核心是单循环即每个参赛选手都要和其他所有选手打一场数学表达是组合数 C(n,2) 场比赛。比如 A 组 6 个人需要打 15 场比赛。循环赛排场次的经典算法是固定轮转法Round-robin tournament把选手编号排成两行第一轮两两配对之后每轮固定一个选手不动其他选手按序号轮转最终生成一张完整的对阵表。这个算法在论文里值得用表格或者伪代码好好讲一讲因为它不是普通的增删改查有算法思想在里面。然后是淘汰赛。乒乓球比赛常见的淘汰赛是从 16 强、8 强、4 强、决赛这样逐级淘汰。如果报名人数不是 2 的幂需要处理轮空bye的情况。实现上可以用一维数组表示晋级树数组下标 0 和 1 的胜者进入下一轮对应数组下标 2以此类推。这个模型用代码实现时就是一个 while 循环逐轮生成下一轮的对阵记录。赛程状态流转也很关键。比赛未签到、进行中、已完结每个阶段都有不同的操作权限。录入比分之后服务端自动判断该小组赛的所有比赛是否全部打完如果是就计算出该组积分前两名进入淘汰赛阶段的下一轮。这里我用状态机来描述怎么定义状态、哪些操作触发状态改变论文里画个状态转换表会显得整个系统设计严谨。3.4 比分与排名11 分制下的计算逻辑乒乓球每局 11 分成人比赛通常 7 局 4 胜。比赛结果的录入设计要体现出对这项运动规则的理解。前端录入比分时可以给一个局分形式的表单比如大比分 4:1并附上每一局的小分11:7、11:9、9:11、11:6、11:8。后端校验大比分是否为四局两胜或三局两胜双方小分是否合法。如果 10 平则需要领先 2 分才能赢下这一局比如 12:10 或 13:11这些规则要在校验逻辑里体现出来。录入完成后系统要做三件事第一更新本场赛程的状态为已结束并关联比赛结果第二更新运动员在本次赛事的胜负记录第三如果本场属于小组赛要重新计算所在小组的积分排名。这里积分规则可以设计得很直观胜一场积 2 分负一场积 1 分弃权积 0 分。排名越高的中国选手通常会比较小分和净胜局数这个逻辑很简单但含金量还不错先比积分积分相同比胜负关系胜负关系再相同则比较净胜局数。排名的计算如果只做一张排名表就太简单了。我建议在 ranking 表里把每个运动员的胜场、负场、积分、净胜局、排名动态算出来每次比分更新都重算这个组的排名。虽然这样做略显冗余但好处是前端查询排行时不用现场聚合大量数据查询速度快展示也直接。如果想让系统性能更优可以使用定时任务或异步更新不过毕设阶段用同步重算完全够用把逻辑先写清楚最重要。4. 实操过程与部署避坑指南4.1 本地跑通项目的三个步骤第一数据库初始化。我建议你直接用我整理好的init.sql脚本创建数据库并将建表和基础数据一次性导入。千万要注意在配置文件中修改数据库名、用户名、密码。这里最诡异的地方是如果 MySQL 装在本机连接串里的 localhost 一般没问题但如果你的 MySQL 是装在某台远程主机上或者使用了云数据库连接串一定要改成对外可访问的 IP并确保数据库账号有远程访问权限。做毕设的时候很多时间浪费在代码没错但连不上库这种环境问题上。第二启动后端。用 IDEA 打开工程文件先让 Maven 把依赖全部拉下来然后找到SpringBootApplication的启动类运行 main 方法。如果启动报错99% 是配置文件里的数据库连接出了问题优先检查 IP、端口、数据库名、账号密码这四项。第三启动前端。进入 vue 前端工程目录执行npm install安装依赖再执行npm run dev启动开发服务器。然后浏览器打开前端地址用管理员账号登录把角色权限的基础数据看一遍。4.2 这些配置坑我每年帮学生踩第一个大坑是 Spring Boot 版本过高。有学生直接从官网下载了 3.x 版本然后把 Spring Security、MyBatis Plus 等依赖配到一起启动时各种类找不到最后折腾了两天才发现是版本兼容问题。老实说尽量锁定 2.7.18 版本这是我踩坑后最稳的组合。控制好版本你的毕设项目就不会在依赖上翻车。第二个坑是跨域配置。前后端分离模式下后端默认不允许来自不同端口的前端请求。需要写一个 CORS 配置类允许指定的前端地址比如 http://localhost:8080跨域访问。如果不配置前端页面调接口时会报 No Access-Control-Allow-Origin header is present。这个报错太常见了把跨域配置写好你后面就不用因为要允许所有域名而采取过于宽松的方案。第三个坑是文件上传和静态资源映射。如果需要上传运动员头像图片Spring Boot 默认的静态资源目录是 classpath:/static/如果你把图片传到服务器本地的其他目录前端就访问不到。需要自定义资源配置映射本地路径到 URL 路径。这个知识点在答辩时也常会被问建议好好看。第四个坑是日期类型在前后端的 JSON 序列化。后端返回LocalDateTime类型时默认的序列化格式可能是 2024-05-01T12:00:00前端显示出来不太友好。需要在配置里指定统一的日期格式为 yyyy-MM-dd HH:mm:ss。这个过程让我想起服务器时区设置如果你的服务器时区不是中国时区响应的时间会差 8 个小时这个问题在生产环境里很容易遇到要多留个心眼。4.3 打包部署到服务器的实战记录本地开发完成后最终要打包部署。按我的习惯先把前端工程执行npm run build生成 dist 目录。这个目录里就是纯 HTML、CSS、JS 静态文件。接着处理后端在后端工程根目录执行mvn clean package -DskipTests生成 jar 包。在服务器上使用nohup java -jar springboot-pingpong-1.0-SNAPSHOT.jar app.log 21 这样一条命令启动项目。然后需要配置 Nginx 或使用 Spring Boot 内嵌的静态资源映射来托管前端 dist 文件。因为我的前端和后端最后是部署在同一台服务器上的为了省事我用的是第三种方式把 dist 目录拷到 Spring Boot 的 classpath:/static/pingpong/ 下这样用户访问的时候就是同一个端口完全没有跨域问题部署量最少。这个方案在功能演示时非常好看也减少了答辩前一天的紧张程度。5. 答辩要点与后续扩展方向5.1 评委老师最常问的几个问题答辩环节我的经验是评委对毕设项目的考察主要集中在三个方面工作量是否真实、核心逻辑是否理解、碰到问题能否解决。第一个高频问题是你介绍一下数据库表结构为什么要这么设计。这里你就把七张表的关系讲一遍user 和 player 是一对一competition 到 event 是一对多event 到 registration 是一对多schedule 则是比赛的产生记录。再把外键字段说清楚这是一道送分题。只要你能在纸上画出来就算过。第二个高频问题是赛程编排是怎么实现的讲讲你的算法。这时候拿出你在论文里写的固定轮转法和二叉树晋级模型说清楚每轮对阵是怎么生成的、轮空如何处理、限制条件是什么。如果你能现场在白板上比划几步说服力非常强。第三个高频问题是如果报名人数特别多系统会不会卡你怎么优化。这个问题其实在考察你有没有思考过性能。可以回答给 registration 表的 competition_id event_id 建联合索引在赛程查询接口做分页如果规模再大用 Redis 缓存报名人数用消息队列做异步编排。别说太多点到 Redis 和索引就够这证明你有这个意识。第四个高频问题是你在这个项目里觉得最坑的一个 bug 是什么。千万别回答没有 bug或者登录不好用这种话。说一个真实存在并且成功解决的 bug 会好很多。比如我在开发时遇到的小组赛打完排名计算不对问题两选手积分相同时没有优先看胜负关系导致某组前两名晋级错误。定位思路是把排名逻辑单测然后添加了新的排序规则重新跑测试就通过了。这种真实问题一句话就能说明白但很能体现你的调试能力。5.2 这套系统还能怎么扩展如果你学有余力可以让系统看起来更有竞争力。第一个扩展方向是做数据可视化。赛事数据进行图形化展示比如报名人数趋势图、各项目参赛比例、球员胜率分布实现方式可以是 ECharts 前端图表加后端聚合接口。另一个方向是引入 Redis 做缓存热点数据、用 RabbitMQ 做赛程编排的消息通知。不过做这些扩展的前提是先确保核心功能稳定如果时间不足可以把这些作为后期展望写进论文同样能换到印象分。还有一个实用的扩展是导出 Excel 功能。老师评委经常喜欢看一键导出秩序册或者导出积分表这类功能。用 EasyExcel 导出可以在现场快速演示也很容易讲解其实值得加。6. 从经验中提炼的几条建议带完一届又一届学生有些话每次都会重复说。技术方面不要把时间浪费在反复重构代码上先把主流程跑通再考虑优化要从跑起来的目标出发去取舍。论文的写法上别把代码大段大段贴到论文里这是大忌。论文要着重写业务流程、表结构设计、核心算法、系统测试代码只挑关键方法的小片段来佐证设计思路。查重方面论文中涉及技术概念的段落建议用自己的话重新组织一遍尤其是从网上抄来的系统背景、研究意义等部分被查重标记出来会是一件很烦人的事。综合来看springboot乒乓球赛事管理系统是一个性价比很高的毕设选题后端用 Spring Boot 构建核心服务前端用 Vue 或 Thymeleaf 呈现再结合 MySQL 完成数据存储整条链路清晰、主流、可讲。你把这个项目认真做完收获的不仅仅是一个毕设分数更是一套完整的 Web 项目开发和部署的实践经验。答辩那天你如果能现场把赛程编排、比分录入、积分排名一气呵成地演示下来再对评委的问题有条理地讲出设计思路基本稳了。
返回列表