ARTICLE DETAIL

资讯详情

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

Java+SpringBoot选课系统源码实战:冲突判断、并发控制与毕设避坑指南

Java+SpringBoot选课系统源码实战:冲突判断、并发控制与毕设避坑指南 简介这份资源是面向计算机专业学生与Java Web开发初学者的毕业设计完整源码包主题为基于JavaSpringBoot的学生网上选课系统配套Vue.js前端可用于课程设计、毕设答辩或自学练手。系统覆盖教室、教师、课程、教学计划、选课、成绩、学生等管理模块并通过角色权限区分管理员、教师与学生三类用户完整呈现了选课冲突处理、成绩录入导出等典型业务场景。压缩包共417个文件约22.15MB以109个Java后端源码、56个Vue组件、161个svg图标资源为主另含js、xml、yml、sql、css及说明文档等结构清晰、便于按模块阅读。目前已有114人学习下载。读者可据此获得一套可直接运行参考的完整项目方案理解SpringBoot与Vue的前后端分离写法、数据库表设计与权限控制思路适合作为毕设选题与实战提升的参考素材。1. 从一份能跑通的选课系统源码说起它到底解决了毕设里的哪些硬骨头如果你正在为 Java 毕设发愁大概率会遇到一个尴尬局面需求文档写得漂亮真到写代码时选课冲突、并发抢课、权限分级这几个点全卡住。这份基于 Java SpringBoot 的学生网上选课系统源码恰好就是冲着这些硬骨头去的。它不是那种只有增删改查的玩具工程而是把学生、教师、管理员三种角色的完整业务闭环都跑通了——学生选课退课、教师录入成绩、管理员维护课程容量每一块都有对应的接口和页面。适合谁适合已经学过 Java 基础、能看懂 SpringBoot 注解、但还没独立搭过一个多角色业务系统的同学。你拿到手之后最直接的价值是不用从零设计表结构不用纠结选课冲突怎么判照着源码把逻辑捋一遍毕设的核心模块就有了。2. 拆开工程看骨架SpringBoot 分层与 Vue 前端的对接方式2.1 后端目录结构里藏着哪些必改的配置拿到源码先别急着点运行花十分钟把目录结构看清楚后面能省掉大量翻车时间。典型的 SpringBoot 选课系统后端一般长这样src/main/java/com/example/course/ ├── controller/ // 接口层处理前端请求 ├── service/ // 业务逻辑选课冲突判断在这里 ├── mapper/ // MyBatis 数据访问接口 ├── entity/ // 数据库实体类 ├── config/ // 跨域、拦截器、MyBatis 配置 └── CourseApplication.java // 启动类 src/main/resources/ ├── application.yml // 数据库连接、端口、MyBatis 映射 ├── mapper/ // XML 映射文件 └── static/ // 前端打包后的静态资源这个结构是 SpringBoot 项目里最常见的一种controller 只负责接收参数和返回结果真正的选课逻辑写在 service 层。你重点看两个文件application.yml和config/下的跨域配置。前者决定你能不能连上数据库后者决定前端能不能调通接口。# application.yml 关键配置 server: port: 8080 # 后端启动端口和前端代理对应 spring: datasource: url: jdbc:mysql://localhost:3306/course_selection?useSSLfalseserverTimezoneAsia/Shanghai username: root password: 你的密码 driver-class-name: com.mysql.cj.jdbc.Driver jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: GMT8 mybatis: mapper-locations: classpath:mapper/*.xml type-aliases-package: com.example.course.entity这段配置里server.port如果被占用就改成 8081 或 9090但改完后前端代理也要同步改。url里的serverTimezone必须加否则 MySQL 8 会报时区错误。mapper-locations指向 XML 文件位置少一个星号都会导致 MyBatis 找不到映射。我一般会先把数据库建好、导入 SQL再启动后端这样报错信息最干净。2.2 前端 Vue 工程怎么和后端接口对齐前端如果是 Vue 写的通常会有vue.config.js或vite.config.js做代理。很多同学把前端打包后直接扔进 SpringBoot 的static目录结果页面能打开但接口 404问题就出在代理没配对。// vue.config.js 开发环境代理配置 module.exports { devServer: { port: 8081, proxy: { /api: { target: http://localhost:8080, // 后端地址 changeOrigin: true, pathRewrite: { ^/api: } // 去掉 /api 前缀 } } } }target写后端实际启动的地址和端口pathRewrite的作用是前端请求/api/student/list时实际打到后端的是/student/list。如果你后端 controller 上已经写了RequestMapping(/api/student)那这里就不需要重写否则会变成/api/api/student。常见做法是前后端约定一个统一前缀要么都在后端加要么都在代理里去掉别两边都加。打包上线时把npm run build生成的dist目录内容复制到src/main/resources/static下然后重新启动 SpringBoot访问http://localhost:8080就能看到页面。注意 Vue Router 如果是 history 模式刷新页面会 404需要在后端加一个转发配置或者改成 hash 模式。3. 选课冲突与并发控制业务层最该盯住的几段代码3.1 时间冲突判断的 SQL 与 Java 双重校验选课系统最核心的逻辑不是增删改查而是“这门课我能不能选”。冲突判断一般分两层数据库层用 SQL 查已选课程的时间段Java 层再做一次精确比对。先看 SQL-- 查询某学生已选课程中与目标课程时间重叠的记录 SELECT c.course_name, c.schedule FROM course c JOIN student_course sc ON c.id sc.course_id WHERE sc.student_id #{studentId} AND c.semester #{semester} AND c.schedule #{targetSchedule}这个查询假设schedule字段存的是类似“周一 1-2 节”这样的字符串直接等值匹配就能判断是否撞课。如果时间段存的是开始节次和结束节次两个数字SQL 就要改成范围重叠判断SELECT COUNT(*) FROM student_course sc JOIN course c ON sc.course_id c.id WHERE sc.student_id #{studentId} AND c.day_of_week #{dayOfWeek} AND c.start_section #{endSection} AND c.end_section #{startSection}Java 层拿到结果后再判断课程容量是否已满、是否已选过同一门课。我一般会把这三个校验按顺序写先查是否已选再查时间冲突最后查容量。顺序不能乱否则会出现“容量没满但时间冲突”的误判。public String selectCourse(Long studentId, Long courseId) { // 1. 是否已选 int count studentCourseMapper.countByStudentAndCourse(studentId, courseId); if (count 0) return 你已经选过这门课; // 2. 时间冲突 Course target courseMapper.selectById(courseId); int conflict studentCourseMapper.countConflict(studentId, target); if (conflict 0) return 与已选课程时间冲突; // 3. 容量判断 if (target.getSelected() target.getCapacity()) return 课程已满; // 4. 写入选课记录并更新已选人数 studentCourseMapper.insert(studentId, courseId); courseMapper.incrementSelected(courseId); return 选课成功; }这段代码里countConflict对应上面的 SQLincrementSelected是一条UPDATE course SET selected selected 1 WHERE id ? AND selected capacity。注意最后这个AND selected capacity很关键它利用数据库行锁防止超卖比在 Java 里判断更可靠。3.2 高并发下怎么防止课程被超选毕设答辩时老师常问一句“如果很多人同时抢一门课你的系统扛得住吗” 其实不用真扛住但你要知道问题在哪。上面那条UPDATE ... WHERE selected capacity就是最朴素的乐观锁在 MySQL 默认隔离级别下能保证不超卖。如果还想再稳一点可以在 service 方法上加Transactional把选课记录插入和人数更新放在同一个事务里。Transactional(rollbackFor Exception.class) public String selectCourseWithLock(Long studentId, Long courseId) { // 先查容量再更新利用行锁 Course course courseMapper.selectForUpdate(courseId); // SELECT ... FOR UPDATE if (course.getSelected() course.getCapacity()) { return 课程已满; } // ... 冲突判断 courseMapper.incrementSelected(courseId); studentCourseMapper.insert(studentId, courseId); return 选课成功; }selectForUpdate会在查询时锁住这一行其他事务要等锁释放才能读。代价是并发性能下降但毕设场景完全够用。常见做法是只在容量紧张的热门课上用普通课程走普通查询就行。提示如果数据库表用的是 MyISAM 引擎行锁不生效必须改成 InnoDB。建表时加ENGINEInnoDB DEFAULT CHARSETutf8mb4。4. 避坑与排查从环境到权限的五个血泪教训4.1 数据库连不上先看这三个地方现象启动 SpringBoot 直接报Communications link failure或Access denied for user。原因通常不是代码问题而是 MySQL 服务没启动、端口不对、或者用户名密码写错。解决先确认 MySQL 服务在运行再用mysql -u root -p手动登录一次能登进去说明账号没问题。然后检查application.yml里的url端口是不是 3306password有没有被引号包错。如果 MySQL 8 报Public Key Retrieval is not allowed在 url 后面加allowPublicKeyRetrievaltrue。4.2 前端页面空白控制台报 404 或跨域现象浏览器打开页面一片白F12 看到GET http://localhost:8080/api/... 404或者CORS policy错误。原因前端代理没配、后端接口路径对不上、或者后端没加跨域配置。解决先看 Network 里请求的实际地址如果是localhost:8081/api/...说明代理没生效检查vue.config.js是否重启。如果是 404对比后端 controller 的RequestMapping和前端请求路径差一个字母都不行。跨域问题在后端加一个WebMvcConfigurer配置即可Configuration public class CorsConfig implements WebMvcConfigurer { Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(/**) .allowedOriginPatterns(*) .allowedMethods(GET, POST, PUT, DELETE) .allowCredentials(true) .maxAge(3600); } }注意allowedOriginPatterns和allowedOrigins的区别前者支持通配符且允许携带凭证后者在 SpringBoot 2.4 以后不能和allowCredentials(true)共用。4.3 选课成功但已选人数没变现象学生选课提示成功但课程列表里已选人数还是 0。原因插入选课记录和更新课程人数不在同一个事务里或者更新语句条件没写对。解决检查 service 方法有没有Transactional再看UPDATE语句的WHERE条件是不是id ? AND selected capacity。如果selected初始值是 nullnull capacity结果为 false更新不会执行。建表时给selected设默认值 0。4.4 教师和管理员登录后看不到对应菜单现象三种角色都能登录但教师登录后看到的是学生菜单。原因前端路由守卫或后端接口权限没做角色区分。解决登录接口返回用户角色字段前端存到 localStorage 或 Vuex路由跳转时根据角色加载不同路由表。后端在拦截器里校验角色比如/teacher/**只允许role teacher的 token 访问。常见做法是用一个RoleCheck(teacher)自定义注解加拦截器实现。4.5 打包后静态资源 404CSS 和 JS 加载失败现象npm run build后把dist放进static访问页面只有 HTML样式和脚本全 404。原因Vue 打包默认publicPath是/但 SpringBoot 静态资源路径可能带上下文。解决在vue.config.js里设publicPath: ./重新打包。如果用了 Vue Router 的 history 模式还要在后端加一个 fallback 到index.html的配置否则刷新子页面会 404。5. 二次开发与验证把毕设源码改成能写进论文的版本5.1 加一个选课时间窗口控制原始源码可能没做选课时间限制任何时间都能选。你可以在application.yml里加两个配置项然后在 service 层判断当前时间是否在窗口内course: selection: start-time: 2025-03-01 08:00:00 end-time: 2025-03-15 22:00:00Value(${course.selection.start-time}) private String startTime; Value(${course.selection.end-time}) private String endTime; public boolean isSelectionOpen() { LocalDateTime now LocalDateTime.now(); LocalDateTime start LocalDateTime.parse(startTime, DateTimeFormatter.ofPattern(yyyy-MM-dd HH:mm:ss)); LocalDateTime end LocalDateTime.parse(endTime, DateTimeFormatter.ofPattern(yyyy-MM-dd HH:mm:ss)); return now.isAfter(start) now.isBefore(end); }在selectCourse方法开头调用isSelectionOpen()不在窗口内直接返回提示。这个改动小但论文里能写一节“选课时间控制策略”答辩时也有东西讲。5.2 用 Postman 或 curl 验证接口链路改完代码别急着开浏览器先用 curl 把核心接口跑一遍确认后端逻辑没问题# 登录获取 token curl -X POST http://localhost:8080/login \ -H Content-Type: application/json \ -d {username:student1,password:123456} # 用 token 选课 curl -X POST http://localhost:8080/student/select \ -H Content-Type: application/json \ -H token: 上一步返回的token \ -d {courseId: 101}如果返回{code:200,msg:选课成功}说明后端链路通了。再打开前端页面操作一遍确认前后端联调没问题。我一般会准备三个账号学生、教师、管理员每个角色至少跑一遍核心流程这样能提前发现权限遗漏。5.3 数据库索引与查询优化选课系统数据量不大但加几个索引能让查询快很多论文里也能写“性能优化”一节。在student_course表的student_id和course_id上建联合索引ALTER TABLE student_course ADD INDEX idx_student_course (student_id, course_id); ALTER TABLE course ADD INDEX idx_semester_schedule (semester, schedule);第一个索引加速“某学生是否选过某课”的查询第二个加速时间冲突判断。建完索引后用EXPLAIN看一下查询计划确认type不是ALL全表扫描。5.4 论文里怎么描述这个系统别把源码里的功能列表直接抄进论文。挑三个点展开一是选课冲突判断的算法逻辑把 SQL 和 Java 双重校验画成流程图二是并发控制讲清楚UPDATE ... WHERE selected capacity为什么能防止超卖三是前后端分离的接口设计列一个接口表写清楚请求方法、路径、参数和返回格式。这样写出来既有技术深度又和源码对得上老师问细节你也能答。从那以后我每次拿到一份毕设源码都先跑通登录和核心业务再动任何代码。先验证再改造比上来就重构靠谱得多。希望帮到你。本文还有配套的精品资源点击获取
返回列表