news 2026/4/15 19:11:04

毕设学校体育场管理系统的设计与实现:新手入门实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
毕设学校体育场管理系统的设计与实现:新手入门实战指南


毕设学校体育场管理系统的设计与实现:新手入门实战指南

摘要:许多计算机专业学生在毕业设计中面临业务逻辑不清、技术栈选型混乱、系统耦合度高等问题。本文以“毕设学校体育场管理系统的设计与实现”为案例,从零开始讲解如何基于 Spring Boot + MyBatis + Vue 构建一个高内聚低耦合的 Web 应用。涵盖场地预约、冲突检测、用户权限控制等核心功能,并提供可运行的代码结构与数据库设计。读者将掌握 MVC 分层实践、RESTful API 设计规范及前后端联调技巧,显著提升毕设开发效率与代码质量。


一、先吐槽:毕设里那些绕不过去的坑

做毕设最怕什么?不是写不出代码,而是“写了一大堆,最后连自己都不想看”。我总结了三条高频痛点,看看你有没有中招:

  1. 需求拍脑袋:老师一句“做个预约系统”,结果连“允不允许重复预约”都没说清楚,写到一半才发现逻辑全崩。
  2. 技术大拼盘:听说微服务火,就把 Spring Cloud 全家桶怼进去;听说 React 酷,又把前端脚手架换成 Next.js。最后服务器 2G 内存,连 IDEA 都跑不动。
  3. 代码能跑就行:一个Controller里写 500 行 SQL,一个jsp里嵌 7 层if,答辩时老师问“如果两个同学同时预约最后一块场地,会咋样?”——当场社死。

如果你也踩过类似的坑,下面的实战路线或许能救你一把。


二、技术选型:别被“网红”框架带节奏

毕设不是双十一,稳定能跑才是硬道理。我对比了四组常见方案,结论直接给:

技术方向候选推荐指数理由
后端Spring Boot 2.7★★★★☆生态成熟,IDE 支持好,出活快;注解驱动,新手易读。
后端Django 4.x★★★☆☆开发快,但 Python 部署对本科生略陌生,服务器装环境易翻车。
前端Vue3 + Vite★★★★☆模板语法贴近 HTML,单文件组件易拆分,导师一眼能看懂。
前端React 18★★★☆☆函数式+Hooks 学习曲线陡,状态管理一乱就炸。

结论:Spring Boot + MyBatis-Plus + Vue3 + MySQL8 是最低成本“能跑+能写+能讲”组合,下文所有示例均基于此。


三、总体架构:一张图先建立共识

  • 前端:Vue-Router 负责页面跳转,Axios 统一拦截器封装 REST 请求。
  • 网关:Spring Security 做 JWT 登录鉴权,全局异常统一返回 JSON。
  • 服务层:MyBatis-Plus 提供通用 Mapper,业务代码只写扩展 SQL。
  • 数据层:MySQL 8.0,事务交给 Spring 声明式,一行注解搞定。

四、数据库设计:提前消灭“并发冲突”

别急着敲代码,先把 ERD 画明白。核心就三张表,其余字典表按需扩展。

  1. 用户表user
    • id/student_no/password/role(admin/user)
  2. 场地表field
    • id/name/type(篮球/足球…) /open_at/close_at
  3. 预约表booking
    • id/user_id/field_id/start_time/end_time/status(预约成功/已取消)

关键约束

  • 联合唯一索引(field_id, start_time)保证同一时段只能有一条“成功”预约。
  • 取消记录逻辑删除,不物理删,方便后续对账。

五、后端核心模块拆解

下面给出 4 个最常见“必考”功能点的实现思路 + 关键代码,每段都带注释,CV 即可用。

1. 用户认证:JWT + RefreshToken 双缓存

Spring Security 配置太长,这里只贴核心过滤器,重点看注释:

public class JwtFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { String token = resolveToken(request); if (token != null && jwtUtil.validate(token)) { // 从 Redis 拿用户信息,避免每次查库 LoginUser loginUser = redisCache.get( RedisKey.access(token), LoginUser.class); if (loginUser != null) { UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken( loginUser, null, loginUser.getAuthorities()); SecurityContextHolder.getContext().setAuthentication(auth); } } chain.doFilter(request, response); } }

幂等性:登录接口/api/login对同一学号并发请求,JWT 签发前用SETNX锁 3 秒,防止重复生成 Token。

2. 场地列表:分页 + 多条件查询

MyBatis-Plus 的LambdaQueryChainWrapper是真香:

public IPage<FieldVo> pageField(FieldPageDTO dto) { return fieldMapper.selectPage( new Page<>(dto.getCurrent(), dto.getSize()), new LambdaQueryWrapper<Field>() .like(StringUtils.isNotBlank(dto.getName()), Field::getName, dto.getName()) .eq(dto.getType() != null, Field::getType, dto.getType()) .orderByAsc(Field::getId) ).convert(FieldVo::fromPo); }

避坑:不要把Page对象直接返回给前端,字段太多会暴露总记录数,统一用 VO 再包一层。

3. 预约调度:并发竞争 + 幂等性

最容易翻车的就是“最后一块场地”。采用“先插后判”策略:

  1. 前端点击预约 → 后端收到fieldId + startTime
  2. 直接执行INSERT … ON DUPLICATE KEY UPDATE
  3. 若影响行数 = 1,说明抢占成功;= 2 则唯一索引冲突,返回“已被预约”
@Transactional public R<Void> book(BookDTO dto)现 { Booking po = new Booking(); po.setUserId(UserContext.getUserId()); po.setFieldId(dto.getFieldId()); po.setStartTime(dto.getStartTime()); po.setEndTime(dto.getEndTime()); po.setStatus(BookingStatus.SUCCESS); // 利用唯一索引兜底 int row = bookingMapper.insert(po); return row == 1 ? R.ok() : R.fail("该时段已被预约"); }

并发测试:用 JMeter 200 线程同时请求,数据库层唯一索引保证最终一致性,应用层无需分布式锁。

4. 取消预约:软删除 + 乐观锁

取消不是DELETE,而是UPDATE status = CANCELLED。同时加版本号防止重复提交:

@Transactional public R<Void> cancel(Long bookingId) { Booking b = bookingMapper.selectById(bookingId); if (b == null || !b.getUserId().equals(UserContext.getUserId())) { return R.fail("无权取消"); } LambdaUpdateWrapper<Booking> wrapper = new LambdaUpdateWrapper<>(); wrapper.eq(Booking::getId, bookingId) .eq(Booking::getStatus, BookingStatus.SUCCESS) .set(Booking::getStatus, BookingStatus.CANCELLED); return bookingMapper.update(null, wrapper) == 1 ? R.ok() : R.fail("取消失败"); }

六、前端必会:Vue3 组合式 API 示例

下面给出“预约时间选择”组件的核心片段,展示如何一次性把日期 + 时段传给后端,避免多次请求。

<template> <el-form :model="form"> <el-date-picker v-model="form.date" value-format="YYYY-MM-DD"/> <el-time-select v-model="form.timeRange" is-range format="HH:mm"/> </el-form> <el-button @click="submit">提交预约</el-button> </template> <script setup> import { reactive } fromvue'; import axios from '@/utils/request'; const form = reactive({ date: '', timeRange: [] }); async function submit() { const [start, end] = form.timeRange; await axios.post('/api/booking', { fieldId: props.fieldId, startTime: `${form.date} ${start}:00`, endTime: `${form.date} ${end}:00` }); ElMessage.success('预约成功'); } </script>

跨域联调:本地用 Vite 代理/apilocalhost:8080,一行配置搞定,无需 CORS 注解:

// vite.config.js server: { proxy: { '/api': { target: 'http://localhost:8080', changeOrigin: true } } }

七、安全加固:别让“小系统”成“大漏洞”

  1. SQL 注入:MyBatis-Plus 的${}#{}千万别混用,凡是外部参数一律#{}预编译。
  2. 会话安全:JWT 只存学号与角色,不存密码;密钥长度 256 bit,定期轮换。
  3. 水平越权:所有“用户级”接口必须带userId = @CurrentUser,并在 SQL 里再判一次,防止接口串改。
  4. 敏感操作日志:预约、取消、结算全部写operate_log表,保留 180 天,老师最爱看审计功能。

八、生产环境避坑指南

  1. 冷启动优化
    Spring Boot 2.7 默认开启devtools,打包时一定exclude,否则服务器 1C2G 启动 60s+。
  2. 事务边界误用
    select上标@Transactional会加长锁时间,读多写少的业务只在insert/update方法加事务。
  3. 时间戳时区陷阱
    服务器 CST、MySQL system_time_zone 不一致会导致“预约成功却查不到”。统一用UTC+0存,前端按浏览器本地时区展示。
  4. 日志级别
    生产环境root: INFO即可,MyBatis SQL 打印记得关,否则 1k 并发能把磁盘打满。

九、可继续扩展的“加分项”

  • 短信通知:接入阿里云/腾讯云,预约成功即发送“时间+场地号”,老师直呼专业。
  • 日历视图:用 FullCalendar 组件,把预约数据渲染成色块,一眼看出空档。
  • 微信小程序:把 Vue 页面直接塞进 UniApp,打包发微信,秒变“互联网+”项目。

十、写在最后

整个系统从 0 到答辩版,我大概用了 4 周,每天 3 小时。最费时的不是写代码,而是“想清楚到底要解决什么问题”。一旦把需求、边界、异常都想明白,代码只是翻译工作。希望这份“踩坑笔记”能让你少走一点弯路,把省下来的时间拿去刷剧、打球、谈恋爱,毕业快乐!


版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/10 13:31:44

LLM智能客服系统效率优化实战:从架构设计到性能调优

背景痛点&#xff1a;高峰期“慢、卡、爆”三连击 去年双十一&#xff0c;我们内部客服系统第一次大促压测就翻车了&#xff1a; 平均响应 2.8 s&#xff0c;P99 飙到 12 s&#xff0c;用户疯狂点“转人工”。8 张 A100 打满&#xff0c;GPU 内存占用 95%&#xff0c;新 Pod …

作者头像 李华
网站建设 2026/3/31 23:03:55

CANN ops-cv解读——AIGC图像生成/目标检测的图像处理算子库

cann组织链接&#xff1a;https://atomgit.com/cann ops-nn仓库链接&#xff1a;https://atomgit.com/cann/ops-nn 在AIGC图像生成、目标检测、图像修复等视觉类场景中&#xff0c;图像处理的效率与质量直接决定了AIGC产品的用户体验&#xff0c;而卷积、池化、图像变换等图像…

作者头像 李华
网站建设 2026/4/10 17:20:35

屏蔽朋友圈三种情况

屏蔽朋友圈的三种情况&#xff1a; 1.只给亲密的人看&#xff1b; 2.觉得你不该看&#xff1b; 3.怕看了不合适内容后有不好印象和想法。

作者头像 李华
网站建设 2026/4/15 9:32:35

【STM32H7实战】QSPI Flash的MDK下载算法开发与调试技巧详解

1. QSPI Flash下载算法开发基础 第一次接触STM32H7的QSPI Flash下载算法时&#xff0c;我也是一头雾水。经过几个项目的实战&#xff0c;我发现理解其核心原理比死记步骤更重要。MDK下载算法本质上是一套运行在RAM中的微型驱动&#xff0c;它通过标准接口与MDK调试器通信&…

作者头像 李华
网站建设 2026/4/15 5:36:09

Java实战:构建高可用AI智能客服回复系统的架构设计与实现

背景痛点&#xff1a;电商大促下的“三座大山” 去年双十一&#xff0c;我负责的智能客服系统差点被流量冲垮。复盘时&#xff0c;我们把问题收敛到三个最痛的点&#xff1a; 响应延迟&#xff1a;高峰期 TP99 飙到 3.2 s&#xff0c;用户一句“怎么退款”要转半天圈&#xf…

作者头像 李华