
1. 项目定位为什么是“马拉松赛事服务一体化平台”老实说我第一次看到“springboot马拉松赛事服务一体化平台”这个选题时第一反应是“这不又是校园里最常见的管理系统吗”。但真正把标题里的“一体化”三个字拆开细想才发现它和普通的学生管理、图书管理系统完全不是一个量级。马拉松赛事服务要覆盖的环节非常多赛事信息发布、线上报名、参赛审核、比赛排队、成绩录入、成绩查询、完赛证书下载、数据统计甚至还有跑者论坛和赛事公告整个过程横跨前台展示和后台管理角色又可以分为普通跑者、赛事主办方、系统管理员三类。这种多角色、多流程、多状态流转的业务模型恰恰是毕业设计里最稳的一类选题既不会简单到没有东西可写也不会复杂到一个人半年做不完。现在很多同学选毕设题目习惯性往“电商系统”“新闻发布系统”上靠这类题目十年前的学长学姐已经写到吐了开题报告和答辩时老师一眼就能看出有没有新意。马拉松赛事服务一体化平台的好处在于业务场景足够垂直而且近几年路跑赛事、马拉松比赛越来越火无论是学校体育部还是社会上的赛事公司确实有数字化管理的需求。拿这个题目去讲“你解决了什么实际问题”一定比“我做一个商品增删改查”更有说服力。对答辩老师来说这是一个听得懂、看得出工作量、还能现场演示完整业务流程的选题天然具备拿高分的基础。这篇文章我会从选题拆解、功能设计、技术选型、具体编码、部署上线五个维度把这类 Spring Boot 一体化平台项目的完整做法梳理一遍。无论你是直接用这个题目当作毕业设计还是拿到题目后想改成智慧校园、场馆预约、乡村振兴文旅平台等其他方向这一套思路都能直接复用。1.1 马拉松赛事数字化到底要解决什么实际问题线下马拉松赛事的传统组织方式痛点非常明显。报名阶段靠填 Excel 表收集选手信息缴费靠人工核对转账记录选手名单变更靠群里反复艾特比赛结束之后成绩统计更是要等很久。到了赛事当天检录处还在翻纸质名单核对身份完赛后想查一张电子证书都找不到入口。这些场景一旦放到线上就是一张清晰的功能地图公告发布、赛事列表、在线报名、报名审核、缴费状态、赛程安排、成绩录入、成绩排行、证书生成、数据大屏。所以做这个系统不能把它当成简单的“增删改查背课文”而是要把它当成一次业务流程再造。我在给参赛选手做功能规划时会习惯性地把使用路径画成一条线用户从首页看到赛事公告点进赛事详情页了解比赛时间、地点、报名费、比赛项目填写报名表单提交身份证信息、联系方式、紧急联系人等待主办方审核审核通过后缴费比赛当天通过赛号查询检录信息跑完后在系统里查成绩、下载完赛证书。这条线看起来很长但它才是“一体化”三个字的真正含义不是把几个功能模块堆在一起而是把参赛的完整生命周期都装进同一个平台。1.2 三个角色三条主流程这类平台的用户角色一般分三类普通跑者前台用户、赛事主办方平台运营人员、系统管理员超级管理角色。三个角色各有各的工作台也各有各的权限边界。角色核心职责主要操作普通跑者浏览赛事、在线报名、查成绩注册登录、报名参赛、查看赛事详情、成绩查询、证书下载赛事主办方发起和管理赛事发布赛事、审核报名、录入成绩、管理公告、导出报名名单系统管理员维护平台基础数据用户管理、角色权限、赛事分类、数据统计、全局配置三条主流程里最核心也最容易出错的是报名流程。这里有一个很多同学会忽略的状态设计报名状态不要只设置“已报名”和“未报名”至少要拆成“待审核、审核通过、审核拒绝、已缴费、已取消”这么几个状态。因为马拉松报名往往涉及缴费和资格审核如果只用一个布尔字段后面做查询、统计、退赛处理时会非常痛苦。我见过很多毕设项目就是因为状态设计太简单后面答辩演示时一操作就露馅。2. 核心功能模块与应用场景的完整拆解把需求理清楚之后下一步就是功能模块的设计。这个项目几乎可以照着一个标准的管理平台模板来拆但每个模块都要结合马拉松赛事的具体业务做定制这样才能让系统看起来“有点东西”而不是教科书里的通用代码。2.1 赛事门户从公告到详情的信息展示系统最外层的部分是赛事门户对应前端首页和赛事列表页。这一块要注意的不是功能有多复杂而是信息架构要合理。首页一般放轮播图、热门赛事、最新公告赛事列表页提供按赛事类型全程马拉松、半程马拉松、迷你跑、亲子跑、按城市、按月份筛选的功能赛事详情页则要完整展示赛事介绍、比赛日期、起跑时间、报名截止时间、比赛路线、报名费用、赛事规模、主办单位、赛事规则。实操时有个小技巧赛事详情千万不要把内容直接塞在一个超长文本字段里。建议设计成两部分基础信息用结构化字段保存方便列表页做筛选和排序赛事介绍、路线图、竞赛规程这类长内容单独放在一个“内容表”里或者用富文本编辑器存 HTML。这样前端展示灵活后台管理也方便。这个设计思路在很多赛事平台里都是标准做法虽然看起来只是一个小选择但实际开发时能省很多事。2.2 报名与审核全链路状态机设计报名模块是这个项目的灵魂功能上要覆盖赛事选择、选手信息填写、报名记录查看、审核状态跟踪、缴费状态更新、取消报名。这里我强烈建议把“报名主表”和“选手明细表”分开设计。什么意思呢一场马拉松比赛中同一个用户可能给家人同时报名好几个项目如果报名字段全部堆在报名表里后面查成绩、导出名单、做统计都会很麻烦。更合理的设计是报名主表保存一次报名行为包含报名人用户ID、关联赛事ID、报名时间、总金额、状态报名明细表保存每一个参赛者的具体信息包括姓名、身份证号、性别、年龄、参赛项目、服装尺码、紧急联系人等。这样一个用户一次报名多个项目在系统里就是一条主记录加多条明细记录结构非常干净。成绩录入时按明细表来录一个选手一条成绩逻辑上也不会乱。审核环节同样要设计得严谨一点。主办方在后台看到待审核列表后可以勾选审核通过或者退回退回时必须填写原因。这个“退回原因”字段非常重要因为前端用户需要看到为什么被拒绝否则用户稀里糊涂被拒体验极差也显得系统不专业。审核通过后报名状态变为“已通过”用户在线完成虚拟缴费毕设阶段可以用模拟支付接口状态再更新为“已缴费”。2.3 成绩管理与证书下载比赛结束之后主办方需要把成绩导入系统。这里最实用的方式是后台提供 Excel 模板下载主办方按模板填写赛号、成绩、排名后上传后端用 EasyExcel 或者 POI解析文件把数据批量写入成绩表。手写比赛结束后一条一条录入成绩的做法虽然也能用但在答辩演示时会被老师追问“如果有一万人参赛你怎么录入”所以批量导入这个功能一定要有。成绩表设计上要包含报名明细ID、选手姓名、赛号、成绩用时建议用秒数存储展示时再格式化成“时:分:秒”、净成绩、枪声成绩、总排名、性别排名、完赛状态。用秒数存储成绩是一个细节因为数据库里直接存字符串“02:38:15”没法做排序和比较存成整数秒后用一条 SQL 就能order by展示时再通过工具类转换格式既高效又优雅。完赛证书可以通过后端动态生成。简单一点的做法是生成一张带选手姓名和成绩的图片或 PDF更常规的做法是做一个证书展示页面前端把选手信息渲染到一个固定样式的模板上用户可以直接打印。这里还可以加一个“证书编号”字段用来做真伪校验整体观感会提升很多。2.4 后台管理端基础数据与统计大盘后台管理端是系统能否落地的关键。主办方需要管理的资源包括赛事管理、分类管理、报名审核、成绩录入、公告管理、选手管理。管理员则额外需要用户管理、角色权限管理和系统日志。管理后台的界面可以做得朴素一点但功能一定要齐全尤其是搜索、分页、导出这三个能力必不可少。选手列表要支持按姓名、手机号、赛事名称、报名状态多维搜索还要能一键导出 Excel方便对接线下物料制作。统计模块是这个项目最大的加分项。首页可以放一个数据概览面板展示累计赛事数量、累计报名人数、本月新增用户、完赛率等核心指标。赛事详情页再做一个小型数据可视化看板展示报名人数趋势图、参赛项目占比饼图、年龄段分布图等。这些统计接口用 SQL 的 group by 就能实现再配合前端 ECharts 图表整个项目的完成度立马上一个台阶。3. 技术选型Spring Boot 生态的关键决策与避坑毕设项目的技术栈选择原则只有一条在“老师看得懂”和“企业用得着”之间找一个平衡点。用纯 Servlet JSP太老用微服务拆得像朵云太飘Spring Boot 加一款主流前端框架就是最稳的组合。3.1 为什么 Spring Boot 是毕设的最优解Spring Boot 最核心的价值是“简化配置、快速启动”。它把 Spring 系列框架中大量繁琐的 XML 配置变成了自动配置开发者只需要引入依赖、写好配置项就能快速得到一个可运行的 Web 项目。对于需要三个月完成项目的毕业生来说这意味着可以把更多时间花在业务逻辑上而不是卡在框架整合上。而且 Spring Boot 的生态非常成熟社区资料极多遇到问题搜一下基本都有现成答案这一点对新手非常友好。举个例子如果不用 Spring Boot 而直接搭 Spring MVC单是配置 DispatcherServlet、配置数据源、配置事务管理器、配置视图解析器就能耗掉一整天。而 Spring Boot 项目里application.yml 里写四五行配置加上几个注解这些问题就全部解决了。所以不管从学习成本还是开发效率来说Spring Boot 都是毕设项目的非常合理的选择。3.2 版本别追新Spring Boot 版本太高怎么办很多同学创建项目时会条件反射地选择最新版本结果经常被版本问题折磨得怀疑人生。当前 Spring Boot 已经迭代到了 3.4、3.5 甚至更高的版本部分配套组件在 JDK 版本、MyBatis 依赖兼容性上都有更高的要求。比如 Spring Boot 3.x 要求 JDK 17 及以上部分老教程中的 2.x 写法在 3.x 中会直接报错。再比如 MyBatis-Spring-Boot-Starter 有专门的版本对应关系并不是随便一个版本都能和 Spring Boot 3.4 一起工作。我个人的建议是毕设项目不要盲目追求最新版。只要老师没有硬性要求选择 Spring Boot 2.7.18 或 3.2.x 这种经过大量验证的稳定版本会舒服很多。2.7.x 对应 JDK 8 或 JDK 11对电脑环境要求低3.2.x 对应 JDK 17适合想体现新技术能力的同学。确定版本后MyBatis-Plus、Hutool、EasyExcel 这些三方组件尽量用 Boot 官方或组件官方推荐的版本组合不要全部勾选最新更不要闭着眼睛给 pom.xml 加版本号。3.3 持久层选型MyBatis-Plus 还是原生 MyBatis项目里用 MyBatis 还是 MyBatis-Plus是毕设选型里一个很经典的分岔路口。如果只用原生 MyBatis每一个单表查询都要手写 XML 和 DAO 接口开发量会明显增加而 MyBatis-Plus 在 MyBatis 之上提供了 BaseMapper内置了单表的增删改查、分页、条件构造器常见操作根本不需要写 SQL。对毕设项目来说用 MyBatis-Plus 可以把开发效率提升至少三分之一同时它依然是基于 MyBatis 的老师不会觉得你走偏了。尤其在做条件分页查询时MyBatis-Plus 的 LambdaQueryWrapper 用起来非常顺手。比如筛选状态为“已报名”且赛事名称包含“马拉松”的报名记录只需要在 Service 里构造一个 LambdaQueryWrapper几行代码就搞定完全不需要手写动态 SQL。底层大部分单表查询都能覆盖遇到真正复杂得多表联查再手写 XML 也不迟。3.4 前端方案前后端分离还是服务端渲染前端的技术方案直接决定整个项目的开发模式。我的建议是只要你有一定基础就选前后端分离前端用 Vue 3 Element Plus后端提供纯 RESTful API。理由很简单前后端分离的好处不只是代码结构清晰更重要的是它符合当下企业开发的主流模式答辩时讲出来显得更专业也方便你在简历上写“熟悉前后端分离开发模式”。如果完全不会前端服务端渲染Thymeleaf也是一个选项。Spring Boot 对 Thymeleaf 的支持很成熟将静态页面放在 templates 目录通过 Controller 返回 ModelAndView 渲染页面不需要额外启动一个前端服务。但这样做有一个明显的短板动态交互能力弱数据更新需要刷新页面做复杂表单校验和图表展示时会比较吃力。所以只要时间允许尽量学一点 Vue前后端分离的收益非常可观。4. 实操过程从建表到核心接口实现有了上面的设计下面就是真正的实操环节。我会从数据库设计、项目初始化、配置编写、自动建表、核心接口这几个维度把整个 Spring Boot 项目的搭建过程串一遍。4.1 数据库设计五张核心表怎么建马拉松赛事服务一体化平台的数据库一般至少包含这五张核心表用户表user、赛事表race、报名主表registration、报名明细表registration_item、成绩表race_result再加上公告表notice和系统配置表config。下面给出用户表和赛事表的参考 SQLCREATE TABLE user ( id bigint(20) NOT NULL AUTO_INCREMENT COMMENT 主键ID, username varchar(50) NOT NULL COMMENT 登录账号, password varchar(100) NOT NULL COMMENT 加密密码, nickname varchar(50) DEFAULT NULL COMMENT 昵称, phone varchar(20) DEFAULT NULL COMMENT 手机号, email varchar(100) DEFAULT NULL COMMENT 邮箱, role tinyint(4) DEFAULT 1 COMMENT 角色1-跑者 2-主办方 3-管理员, avatar varchar(255) DEFAULT NULL COMMENT 头像地址, status tinyint(4) DEFAULT 1 COMMENT 状态0-禁用 1-正常, create_time datetime DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间, PRIMARY KEY (id) ) ENGINEInnoDB AUTO_INCREMENT1 DEFAULT CHARSETutf8mb4 COMMENT用户表; CREATE TABLE race ( id bigint(20) NOT NULL AUTO_INCREMENT COMMENT 主键ID, title varchar(100) NOT NULL COMMENT 赛事名称, type varchar(50) DEFAULT NULL COMMENT 赛事类型, city varchar(50) DEFAULT NULL COMMENT 举办城市, start_date date DEFAULT NULL COMMENT 比赛日期, signup_deadline datetime DEFAULT NULL COMMENT 报名截止时间, price decimal(10,2) DEFAULT 0.00 COMMENT 报名费, scale int(11) DEFAULT 0 COMMENT 赛事规模, status tinyint(4) DEFAULT 0 COMMENT 状态0-未发布 1-报名中 2-已截止 3-已结束, detail text COMMENT 赛事介绍, create_time datetime DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间, PRIMARY KEY (id) ) ENGINEInnoDB AUTO_INCREMENT1 DEFAULT CHARSETutf8mb4 COMMENT赛事表;建表时有几个细节值得注意。第一所有表的主键统一叫 id并且使用 bigint 自增这样可以配合 MyBatis-Plus 的默认主键策略第二时间字段统一用 datetime 或 date 类型不要用 varchar 存时间否则后面做范围查询非常痛苦第三状态字段用 tinyint 而不是字符串节省空间配合一个状态字典说明就能解决可读性问题。4.2 项目初始化用 IDEA 创建 Spring Boot 项目创建项目的标准流程是IDEA 里选择 File - New - Project左侧选 Spring Initializr然后填写 Group 和 Artifact。这里有一个高频坑IDEA 内置的 Spring Initializr 地址在某些网络环境下访问超时很多同学卡在这一步就很难受。我自己的处理方式是直接把 Server URL 替换成国内镜像地址比如 https://start.spring.io 换成阿里云的地址创建速度会快很多基本十几秒就能完成初始化。创建完项目后需要在 pom.xml 里加入核心依赖。给出一份参考配置dependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version3.5.7/version /dependency dependency groupIdcom.mysql/groupId artifactIdmysql-connector-j/artifactId scoperuntime/scope /dependency dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency dependency groupIdcom.alibaba/groupId artifactIdeasyexcel/artifactId version3.3.4/version /dependency dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-spring-boot3-starter/artifactId version3.5.7/version /dependency /dependencies如果是 Spring Boot 3.x注意需要引入的是mybatis-plus-spring-boot3-starter而不是老的 starter这是一个很容易踩的版本坑。版本号建议查一下官方 Maven 仓库里对应的最新稳定版不要直接复制网上旧帖子的配置。4.3 Spring Boot MyBatis 当表不存在自动建表“表不存在自动建表”这个问题我在很多群里看到有同学问。首先澄清一点MyBatis 和 MyBatis-Plus 本身不会自动帮你创建表它的职责是操作已经存在的表。如果你希望项目一启动就自动建表有两条主流方案一是使用 Spring Boot 自带的脚本初始化机制二是引入 Flyway 这样的数据库版本管理工具。对于毕设项目最简单的做法是使用 Spring Boot 的spring.sql.init配置。在 src/main/resources 目录下放一个schema.sql里面写好建表语句再在application.yml中配置spring: sql: init: mode: always schema-locations: classpath:schema.sql这样项目每次启动时Spring Boot 都会执行 schema.sql 中的 SQL。配合CREATE TABLE IF NOT EXISTS语句就能实现“表不存在就自动建表”的效果。需要注意MySQL 的驱动要配置允许IF NOT EXISTS语法这本身没问题但如果你使用 PostgreSQL 或 Oracle语法会有差异。还有一个坑是如果使用mode: always每次启动都会重新执行脚本所以脚本里一定要有重复执行保护像CREATE TABLE IF NOT EXISTS就是最基础的容错手段。更正规的方式是使用 Flyway。Flyway 会把数据表结构变更记录到 flyway_schema_history 表里每次启动时自动检查并执行新增的版本脚本。它的优点是所有历史脚本都保留可以追溯数据库结构的演变。但是对毕设项目来说引入 Flyway 会增加一定的学习成本如果你不想额外折腾先走 schema.sql 的方案完全够用。4.4 项目结构与核心代码实现一个合理的 Spring Boot 项目包结构应该按照分包分层的思想组织com.example.marathon ├── config │ ├── MybatisPlusConfig.java │ ├── CorsConfig.java │ └── WebMvcConfig.java ├── controller │ ├── RaceController.java │ ├── RegistrationController.java │ ├── ResultController.java │ └── UserController.java ├── service │ ├── RaceService.java │ ├── RegistrationService.java │ └── impl │ ├── RaceServiceImpl.java │ └── RegistrationServiceImpl.java ├── mapper │ ├── RaceMapper.java │ └── RegistrationMapper.java ├── entity │ ├── Race.java │ ├── Registration.java │ └── User.java ├── common │ ├── Result.java │ ├── PageResult.java │ └── BusinessException.java └── MarathonApplication.java实体类用 Lombok 简化代码。比如 Race 实体中的字段直接用Data注解就能自动生成 getter 和 setter。为了避免前端拿到的字段是 null所有字段最好都加上默认值。Controller 层的命名规范也很重要尽量使用 RESTful 风格比如新增赛事用 POST /api/race修改赛事用 PUT /api/race查询详情用 GET /api/race/{id}。下面是赛事列表接口的一个简单示例RestController RequestMapping(/api/race) RequiredArgsConstructor public class RaceController { private final RaceService raceService; GetMapping(/list) public ResultPageResultRace list(RequestParam(defaultValue 1) Integer page, RequestParam(defaultValue 10) Integer size, RequestParam(required false) String type, RequestParam(required false) String city, RequestParam(required false) Integer status) { return Result.success(raceService.queryRacePage(page, size, type, city, status)); } }4.5 用户认证与报名的核心逻辑用户登录是几乎所有系统的入口。建议不要自己写复杂的密码加密算法直接用 Spring Security 的 BCryptPasswordEncoder或者使用 Hutool 的 BCrypt 工具类对密码做加盐加密。数据库里永远不要明文保存密码这一点即使毕设项目也必须有。登录成功后可以生成一个 JWT 令牌返回给前端前端在请求头里携带 token后端通过拦截器解析 token 获取用户信息。报名接口是整个系统的重点。用户报名时后端要做几件关键校验第一赛事当前必须处于“报名中”状态第二报名截止时间未过第三用户还没有报过这场赛事第四当前报名人数没有超过赛事规模。校验通过后新增一条报名主记录和若干条明细记录并同时更新赛事的已报名人数。如下是报名方法的核心逻辑Transactional(rollbackFor Exception.class) public Long signUp(Long userId, Long raceId, ListRegistrationItem items) { Race race raceMapper.selectById(raceId); if (race null) { throw new BusinessException(赛事不存在); } if (race.getStatus() ! 1) { throw new BusinessException(当前赛事不在报名时间内); } if (LocalDateTime.now().isAfter(race.getSignupDeadline())) { throw new BusinessException(报名已截止); } Long signedCount registrationMapper.selectCount( new LambdaQueryWrapperRegistration() .eq(Registration::getUserId, userId) .eq(Registration::getRaceId, raceId) .eq(Registration::getStatus, 1) ); if (signedCount 0) { throw new BusinessException(您已报名该赛事请勿重复报名); } Registration registration new Registration(); registration.setUserId(userId); registration.setRaceId(raceId); registration.setStatus(0); registration.setCreateTime(LocalDateTime.now()); registrationMapper.insert(registration); items.forEach(item - { item.setRegistrationId(registration.getId()); registrationItemMapper.insert(item); }); race.setSignedCount(race.getSignedCount() 1); raceMapper.updateById(race); return registration.getId(); }这里必须加上Transactional事务注解。因为报名逻辑同时更新了报名主表、明细表和赛事表的字段任何一个环节失败都必须回滚否则会出现用户报名成功但赛事人数没增加的脏数据。事务是后端开发的基本功在毕设项目里体现出来是非常牢固的加分项。5. 部署上线前后端联调与 Docker 打包项目开发完成后能不能把系统跑起来给老师看是决定最终成绩的重要一关。很多同学在本地运行没问题一到服务器部署就各种翻车。下面这几个环节是我自己反复踩过坑之后总结出来的。5.1 前后端分离的跨域与联调前后端分离项目前端跑在 5173 端口Vite 默认后端跑在 8080 端口两者端口不一致就会产生跨域问题。解决跨域最简单的方案是后端写一个 WebMvcConfigurer 配置统一放行跨域请求。示例代码如下Configuration public class CorsConfig implements WebMvcConfigurer { Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(/**) .allowedOriginPatterns(*) .allowedMethods(GET, POST, PUT, DELETE, OPTIONS) .allowedHeaders(*) .allowCredentials(true) .maxAge(3600); } }注意allowCredentials(true)时allowedOrigins(*)会产生冲突需要改成allowedOriginPatterns(*)才能正常工作。这个细节非常隐蔽很多人卡在这里很久。前端开发环境下Vite 还可以通过配置server.proxy将/api开头的请求代理到http://localhost:8080这样也能解决跨域且更适合生产环境。5.2 使用 Docker 部署 Spring Boot 项目Docker 是现在企业部署项目的标配也是简历里可以放心写的技术点。Spring Boot 项目打包成 jar 包之后编写一个 Dockerfile 就能生成镜像。一个典型的最小 Dockerfile 如下FROM openjdk:17-jdk-alpine WORKDIR /app COPY target/marathon-0.0.1-SNAPSHOT.jar app.jar EXPOSE 8080 ENV TZAsia/Shanghai ENTRYPOINT [java, -jar, app.jar]构建镜像并启动容器的命令如下mvn clean package -DskipTests docker build -t marathon-server:latest . docker run -d -p 8080:8080 --name marathon-server \ -e DB_HOST你的数据库地址 \ -e DB_USERroot \ -e DB_PASSWORD你的密码 \ marathon-server:latest在 application.yml 中数据库地址等信息建议使用环境变量占位spring: datasource: url: jdbc:mysql://${DB_HOST:localhost}:${DB_PORT:3306}/marathon?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: ${DB_USER:root} password: ${DB_PASSWORD:root}这样做的好处是代码仓库里不会出现真实密码部署时通过环境变量注入既安全又灵活。5.3 服务器部署的安全提示部署到服务器后有几个安全细节要特别小心。第一个是 Spring Boot Actuator 的问题如果 pom 里引入了 actuator 依赖而配置里又没有关闭暴露端点就会有敏感信息泄露的风险比如 heapdump 端点可能被利用来导出堆内存信息进而威胁系统安全。非必要不引入 actuator如果要引入只开放健康检查端点management: endpoints: web: exposure: include: health,info第二个是不要用 root 账号直接跑 jar建议在服务器上单独创建一个普通用户来运行应用。第三个是给 MySQL 的账号设置最小权限只授权应用需要的库这个在项目答辩时如果被问到也是加分项。6. 常见问题排查与我的改造建议任何一个项目都不会一帆风顺这里我整理了一份高频问题速查表基本覆盖了 Spring Boot 毕设项目的典型报错场景。问题现象可能原因解决方案启动报Port 8080 was already in use端口被占用杀掉占用进程或修改 server.port连接数据库报Access denied for user数据库账号密码错误检查 application.yml 中的账号密码和权限报Unknown database数据库未创建先执行CREATE DATABASE marathon再启动项目启动后表不存在没有执行建表脚本配置 schema.sql 自动初始化或手动执行 SQLIDEA 创建 Spring Boot 项目超时网络无法访问 spring.io换成国内的镜像初始化地址MyBatis-Plus 查询结果字段为 null驼峰命名与下划线映射问题开启map-underscore-to-camel-case: true前端请求接口报 403跨域或认证问题检查 CORS 配置和 JWT 拦截器放行规则使用 Postman 提交 JSON 报 400实体字段类型不匹配检查前端传参名称与后端实体字段是否一致6.1 关于 MyBatis-Plus 控制台打印 SQL开发阶段建议在 application.yml 里打开 SQL 日志方便排查问题mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl控制台会打印每条 SQL 的完整语句和参数联调时帮了大忙。到部署阶段再把这个配置删掉不然日志量太大影响性能。6.2 提高项目完成度的三个改造方向如果完成基本功能后还有时间我强烈建议做下面这三个方向的改造任何一个都能让你的项目脱颖而出。第一个是使用 WebSocket 做一个赛事消息实时推送。比如管理员发布公告后所有在线用户能实时收到通知比赛成绩录入完成后选手端能立刻看到成绩更新提醒。这个功能在实现上并不复杂Spring Boot 对 WebSocket 的支持已经非常完善但体现在答辩效果上却非常亮眼。第二个是增加数据可视化大屏。单独做一个页面展示赛事报名趋势、报名人数分布、完赛率、年龄结构等数据配合 ECharts 的图表和渐变配色不用多少工作量但视觉冲击力完全是另一个级别。第三个是引入简单的缓存机制。比如赛事详情这样的热点数据用 Spring Cache Redis 缓存起来减少数据库压力。注意设计好缓存更新策略赛事状态变更时要把缓存删掉避免用户看到过期数据。这部分代码量不大但能体现你对高并发、性能优化的思考是答辩环节的高频加分话题。6.3 项目答辩时应当重点展示的内容拿到这套系统后答辩演示不要从登录页开始慢慢点那样非常浪费时间。建议提前准备好演示路径先从赛事门户首页切入点进一个正在报名中的赛事详情现场完成一次用户注册和在线报名然后切到主办方后台审核通过再回前台查看报名状态。接着演示成绩导入、成绩查询和证书下载最后切到数据统计页面展示图表。这样一条链路走下来老师能直观地看到整个系统从用户到管理端的完整闭环提问重点也会落在业务设计上压力会小很多。我在实际做这类项目的过程中还有一个体会不要舍不得删除代码。把一个普通的“马拉松赛事服务一体化平台”改成“智慧场馆预约平台”“乡村振兴文旅平台”“校园运动健康管理平台”往往只需要改表名、改字段、改前端文案。但项目训练出的工程思维包括状态设计、事务控制、接口规范、部署流程是真正能迁移到工作里的能力。拿到题目别急着抱怨它普通花心思把每一个环节做扎实普通题目也能做出不普通的成品。