ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

基于Java的学生选课管理系统答辩PPT:从技术骨架到并发扣减实战

2026/9/18 15:41:55 拓冰建站 浏览量
基于Java的学生选课管理系统答辩PPT:从技术骨架到并发扣减实战 简介这份PPT是《基于Java学生选课管理系统》的毕业设计答辩演示文稿面向计算机相关专业准备课程设计、毕业答辩的本科生与指导教师也可供初学SSM架构的开发者梳理项目全貌。围绕学生选课管理系统的设计与实现内容涵盖研究背景与开发意义、经济与技术及操作三方面可行性分析以及登录、课程信息、选修、成绩、作业等界面展示和最终总结能够帮助读者快速理清答辩思路、把握讲稿脉络。压缩包共1个pptx文件体积约20.09MB以图文幻灯片形式组织页面中包含系统架构说明与界面示例便于直接参考排版与内容取舍。目前已有一百余人学习下载适合需要借鉴同类选题答辩框架、了解Vue.js前端配合Mysql与SSM后端方案讲解方式的读者使用可用来对照完善自己的答辩材料或作为项目答辩前的模拟演练参考。1. 答辩PPT不是排版活把你那套 java 学生选课系统的技术决策讲成一条线很多同学把「基于 java 学生选课管理系统答辩 PPT」当成美工活花三天调字体、加动画上台被问一句「课容量并发扣减你怎么保证不超选」就答不上来。评委真正在看的是这套学生选课管理系统从需求、设计、实现到验证能不能自圆其说而 PPT 只是这条线的载体。这篇写给正在做课程设计、毕业设计答辩的人也写给工作几年后回头补 java基础 和项目讲述逻辑的从业者从模块拆分、ER 图、并发扣减代码到演示脚本、压测截图和高频问答逐页说清哪些内容必留、每页放什么证据、代码该贴哪几行。2. 学生选课管理系统答辩PPT的技术骨架模块边界、技术栈页与架构图怎么定答辩 PPT 的前三页评委基本就在判断这套系统有没有真做过。骨架页决定后面所有内容能不能挂得住所以顺序应该是先定角色与模块再定技术栈最后才画架构图和 ER 图。常见做法是把「需求清单 → 模块划分 → 技术选型 → 架构/ER → 页面时间预算」当成固定前五页后面每一页都在回答其中一个问题而不是想到哪写到哪。顺序错了后面讲并发、讲事务都会显得突兀因为评委不知道这些机制是挂在哪个模块上的。2.1 从需求清单到模块边界四个角色先画死学生选课管理系统最容易讲乱的地方是把「权限」和「业务」混在一张图里。我一般先按角色切一刀把每个角色能碰到的用例列成一张表模块图直接从这张表演化出来答辩时被追问也有据可依。角色核心用例边界说明PPT 呈现方式学生查询课程、选课、退课、看课表只能操作本人选课记录用例图 界面截图教师查看选课名单、录入成绩只能看自己开设的课用例图 权限拦截说明教务管理员开课、排课、设容量、开关选课轮次不直接改学生选课记录后台管理页截图系统管理员用户管理、日志审计、数据备份不参与业务数据修改日志页截图切完角色再切模块通常落成五块用户与权限、课程与排课、选课与退课、成绩与统计、日志与公告。模块图用不同底色区分箭头只画调用方向不要画成蜘蛛网。这张图放在第 4 页评委一眼就能看出你的分层意识也为后面讲 AOP 日志、权限拦截做了铺垫。2.2 技术栈页怎么选一张能自证的选型表技术栈页最忌讳堆 Logo。写满两行框架名评委只会问「这些你都用到了吗」。稳妥的做法是用一张表把每一层选型和一个具体理由绑在一起理由要能被代码验证。层次选型写进 PPT 的理由可展示的证据表现层JSP / Thymeleaf / Vue与课程要求一致前后端边界清晰页面截图或接口文档控制层Spring MVC统一参数校验与异常处理全局异常处理器代码业务层Spring AOP用 java动态代理 织入操作日志与事务切面类源码片段持久层MyBatisSQL 可控便于讲清索引与锁Mapper XML 中的扣减 SQL数据库MySQL 8 InnoDB行锁与唯一索引支撑并发扣减表结构 执行计划截图运行环境JDK 17 java容器用容器固定演示环境避免现场翻车Docker 启动命令截图提示写上「用了 Redis」就要准备回答缓存与数据库一致性怎么处理答不上来不如不写把它放到「后续优化」页里更安全。技术栈页底部留一行小字写清楚 JDK 版本和数据库版本因为演示机上的 JDK 和你本机很可能不一样这个细节提前写在 PPT 上现场出问题时你还能圆回来。2.3 架构图与 ER 图的具体画法先有表结构再画框架构图不要从网上扒一张分层图改字先把自己的表列出来再决定图上画几层。核心表通常五张就够学生表、教师表、课程表、选课记录表、排课时间表。课程表里必须预留容量字段和版本字段选课记录表必须有唯一索引这两点直接决定第三章能不能讲下去。-- 课程表capacity 是容量selected_count 是已选人数version 支撑乐观锁 CREATE TABLE course ( id BIGINT PRIMARY KEY AUTO_INCREMENT, course_code VARCHAR(32) NOT NULL COMMENT 课程编号, course_name VARCHAR(64) NOT NULL COMMENT 课程名称, teacher_id BIGINT NOT NULL COMMENT 任课教师, capacity INT NOT NULL DEFAULT 0 COMMENT 课容量, selected_count INT NOT NULL DEFAULT 0 COMMENT 已选人数, version INT NOT NULL DEFAULT 0 COMMENT 乐观锁版本号, status TINYINT NOT NULL DEFAULT 1 COMMENT 1开放 0停开, UNIQUE KEY uk_course_code (course_code) ) ENGINE InnoDB DEFAULT CHARSET utf8mb4; -- 选课记录表唯一索引是防重复选课的最后一道闸 CREATE TABLE course_selection ( id BIGINT PRIMARY KEY AUTO_INCREMENT, student_id BIGINT NOT NULL, course_id BIGINT NOT NULL, term VARCHAR(16) NOT NULL COMMENT 学期如 2024-2025-1, status TINYINT NOT NULL DEFAULT 1 COMMENT 1已选 2已退 3候补, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, UNIQUE KEY uk_student_course_term (student_id, course_id, term), KEY idx_course_status (course_id, status) ) ENGINE InnoDB DEFAULT CHARSET utf8mb4;这两段 DDL 直接截图放进 ER 图页的备注uk_student_course_term和version两个字段在图上用红框标出来。逻辑说明就一句话唯一索引负责「同一个人同一学期同一门课只能有一条记录」版本号负责「多人抢同一个名额时不超卖」。参数说明上capacity是教务设定的上限selected_count是实时值业务上永远只允许selected_count capacity这条不变式就是第 3 章全部代码存在的理由。2.4 十分钟答辩的页面预算表页数不是越多越好十分钟答辩15 到 18 页是舒服的区间。多出来的页只会挤压演示时间而演示恰恰是加分项。页码内容建议时长必须出现的证据1封面题目、姓名、学号、指导教师20 秒题目与系统名一致2选题背景与目标40 秒一句话说清解决什么问题3需求与角色用例60 秒角色用例表4功能模块图60 秒五模块划分图5技术选型表60 秒选型理由表6-7系统架构图 ER 图90 秒分层图、五张核心表8-9选课并发扣减方案120 秒方案对比 扣减 SQL10冲突检测与退课状态机60 秒状态流转图11-13系统演示180 秒真实可跑的操作录屏14测试与压测结果60 秒并发测试结果截图15不足与后续优化30 秒明确列出两到三条这张表建议直接放在 PPT 备注里答辩前对一遍时间。超时的部分通常出在第 8、9 页讲并发而这两页恰恰是评委最想听的所以把演示录屏提前准备好能省下最宝贵的几分钟。3. 选课并发扣减学生选课管理系统答辩PPT里最容易被追问的一页选课是整份 PPT 里唯一一个真正的并发场景也是区分「抄的」和「做过的」分水岭。很多人的系统在单人测试时毫无问题一到选课开放日就超选原因是扣减逻辑写成了「先查再改」两条语句之间存在时间窗。这一章把复现方式、三种方案对比和可贴上 PPT 的代码都过一遍评委追问时你手里有东西。3.1 超选是怎么发生的先查后改为什么要出事典型错误写法是先select出课程对象在 Java 里判断selectedCount capacity然后update设置新的已选人数。两个线程同时读到容量为 1都判断通过都执行 update最终已选人数变成 2。问题不在 Java 代码而在于「判断」和「写入」之间没有任何互斥。复现很简单# 用 Apache Bench 对选课接口打 100 个并发请求课后对比 selected_count 与 capacity ab -n 100 -c 100 -p select.json -T application/json http://localhost:8080/api/selection-n是总请求数-c是并发数两者都设为 100 表示 100 个请求同时发出。跑完直接查数据库如果selected_count大于capacity这张截图就是最好的反面教材放进 PPT 讲「问题发现」比讲十句原理都有用。需要注意的是ab 打的是你自己的本地环境别拿它去压任何线上系统。3.2 三种扣减方案的对比与选择方案核心语句优点代价适用场景悲观锁select ... for update逻辑直观不易写错行锁持有到事务结束并发差选课人数少、管理端操作乐观锁where version ?条件更新无长事务吞吐好冲突时要重试或提示选课开放期的抢课场景预扣减Redis 原子减库存抗并发最高多一套一致性兜底逻辑秒杀类高并发抢课课程设计答辩用乐观锁是最优解代码量小、可解释性强、失败可重试而且能自然引出「影响行数为 0 该怎么办」这个延伸问题。写进 PPT 的时候把方案对比表留一页把乐观锁的具体实现留一页最后把 Redis 预扣减放进「后续优化」这样既体现了方案完整性又不用为没实现的代码负责。3.3 乐观锁的实现让数据库替你做判断-- CourseMapper.xml把判断和写入压进同一条 SQL影响行数为 0 即抢课失败 UPDATE course SET selected_count selected_count 1, version version 1 WHERE id #{courseId} AND status 1 AND selected_count capacity AND version #{version};Service public class SelectionService { Autowired private CourseMapper courseMapper; Autowired private SelectionMapper selectionMapper; /** * return 1 抢课成功0 容量已满或版本冲突-1 课程不可选 */ Transactional(rollbackFor Exception.class) public int selectCourse(Long studentId, Long courseId, String term) { Course course courseMapper.selectById(courseId); if (course null || course.getStatus() ! 1) { return -1; } // 关键带 version 与容量条件的更新由数据库保证原子性 int rows courseMapper.increaseSelected(courseId, course.getVersion()); if (rows 0) { return 0; // 没抢到交给前端提示名额已满请稍后重试 } // 唯一索引 uk_student_course_term 兜底防止重复选课 selectionMapper.insert(studentId, courseId, term, 1); return 1; } }逻辑上分成三步走第一步做快速失败课程不存在或已停开直接返回第二步是真正的扣减version #{version}让并发线程里只有一个能更新成功其余影响行数为 0第三步写入选课记录重复选课由唯一索引拦截触发异常后由全局异常处理器转成友好提示。参数上course.getVersion()是读到的旧版本号不需要手动加一因为 SQL 里已经做了version 1。事务注解里的rollbackFor要写Exception.class否则写记录失败时扣减不会回滚这是实际项目里很常见的坑。注意扣减和写记录必须在同一个事务里两个方法不能分散到不同的 Service 各自开事务否则会出现在扣了容量但记录没写进去的悬空状态。自调用导致Transactional失效也是同一类问题需要走代理调用。3.4 压测截图怎么造让一百个线程同时起跑答辩用的压测结果不能靠手点得写一个能控制起跑时刻的小程序否则线程是陆续启动的并发压力根本不够。让 java线程等待都完成 的标准做法是用CountDownLatch一个发令枪一个终点线。public class SelectPressureTest { public static void main(String[] args) throws Exception { int threads 100; CountDownLatch startGate new CountDownLatch(1); // 发令枪 CountDownLatch endGate new CountDownLatch(threads); // 等所有线程跑完 ExecutorService pool Executors.newFixedThreadPool(threads); AtomicInteger success new AtomicInteger(); for (int i 0; i threads; i) { final long studentId 1000L i; pool.submit(() - { try { startGate.await(); // 全部阻塞在这里保证同一瞬间发起 int r selectionService.selectCourse(studentId, 1L, 2024-2025-1); if (r 1) { success.incrementAndGet(); } } catch (Exception ignored) { // 抢课失败不计入成功数 } finally { endGate.countDown(); } }); } startGate.countDown(); // 扣扳机 endGate.await(); // 主线程等全部结束再统计 System.out.println(容量10实际抢到 success.get()); pool.shutdown(); } }把课程容量设成 10跑完输出「实际抢到 10」再附一张数据库里selected_count的查询结果这两张图放在 PPT 的测试页比任何文字描述都能说明问题。参数上线程池大小与线程数保持一致避免任务排队导致并发失真endGate.await()不加超时是为了等全部结束如果担心压测卡死可以换成带超时的重载并在超时后打印剩余线程数。这套代码平时也常被拿来当 java面试题 里「如何让多个线程同时开始执行」的现成答案一举两得。4. 从 ER 图到冲突检测学生选课管理系统答辩PPT的数据库与业务规则页并发页解决的是「能不能选上」冲突页解决的是「该不该让他选」。一个学生同一时间段只能上一门课这条规则如果只用 Java 判断同样会在并发下失效。这一章把索引设计、时间冲突的 SQL 写法、状态流转和演示环境的兜底方案串起来都是能直接搬进 PPT 的内容。4.1 核心表字段与索引哪些字段必须建索引表名关键字段索引为什么studentid, student_no, class_id主键、uk_student_no学号登录需要唯一courseid, course_code, teacher_id, capacity主键、uk_course_code、idx_teacher按教师查开课列表course_schedulecourse_id, week_day, start_section, end_sectionidx_course_week冲突检测要按星期和节次过滤course_selectionstudent_id, course_id, term, statusuk_student_course_term、idx_course_status防重与统计已选人数sys_loguser_id, operate_time, moduleidx_user_time日志按人按时间检索索引页不要只贴一张表结构图把EXPLAIN的结果一起截下来。挑一条慢查询展示加索引前后rows与type的变化从ALL变成ref这一页的说服力立刻不一样。很多答辩 PPT 的数据库部分全是字段截图评委看不出你到底懂不懂索引。4.2 时间冲突检测两个区间重叠的 SQL 写法冲突判断的本质是两个时间区间是否相交。把每周的上课时间拆成「星期几 起止节次」存进course_schedule相交条件写成两个不等式即可不需要在 Java 里循环遍历课表。-- 判断学生已选课程中是否存在与目标课程时间重叠的记录 SELECT COUNT(1) FROM course_selection cs JOIN course_schedule s1 ON s1.course_id cs.course_id JOIN course_schedule s2 ON s2.course_id #{targetCourseId} WHERE cs.student_id #{studentId} AND cs.term #{term} AND cs.status 1 AND s1.week_day s2.week_day AND s1.start_section s2.end_section AND s2.start_section s1.end_section;逻辑说明s1是学生已经选上的课的时间s2是准备选的目标课时间。两个区间相交的判定就是「甲的开始不晚于乙的结束且乙的开始不晚于甲的结束」返回条数大于 0 说明冲突。参数上status 1必须带上已退课的记录不参与冲突计算这一点漏了会出现「退课后仍然选不上」的诡异现象。返回结果建议在 PPT 里配一张界面截图把冲突提示的具体文案展示出来说明前后端都做了校验。如果课程量不大还有一种更省事的设计把一周 7 天每天 12 节共 84 个时间片用long的位图表示两门课的时间片做按位与结果非零即冲突。这种写法在答辩时是加分项因为它体现你考虑过查询效率把位运算讲清楚比背八股文有说服力得多。4.3 退课、候补与状态流转状态机页怎么画选课记录的状态不要用布尔值至少要有「已选、已退、候补」三个状态否则候补功能没法实现。状态流转单独做一页画出三条边已选到已退学生主动退课selected_count减一、已选到候补管理员调整名额时转候补、候补到已选有名额释放时自动递补。退课的核心 SQL 与扣减方向相反同样要带条件避免把已退的记录再退一次-- 退课只更新状态为已选的记录影响行数为 1 才回滚容量 UPDATE course_selection SET status 2 WHERE student_id #{studentId} AND course_id #{courseId} AND term #{term} AND status 1;退课成功之后再执行update course set selected_count selected_count - 1 where id ? and selected_count 0两条语句放同一个事务。候补递补如果用定时任务实现记得在 PPT 上标注执行周期并说明递补时同样要走乐观锁扣减不能直接改数字否则候补逻辑会绕过并发保护。4.4 演示环境的兜底java环境变量与容器化启动答辩机不是你的开发机最常见的翻车是 JDK 版本不一致导致编译不过或者数据库没启动。兜底方案有两层一是把 java环境变量 写清楚二是用 java容器 把中间件固定下来。# 1. 确认 JDK版本必须与编译时一致例如 17 export JAVA_HOME/usr/lib/jvm/java-17-openjdk-amd64 export PATH$JAVA_HOME/bin:$PATH java -version # 2. 用容器起一个带初始数据的 MySQL端口与配置文件保持一致 docker run -d --name scm-mysql \ -p 3306:3306 \ -e MYSQL_ROOT_PASSWORDscm123456 \ -e MYSQL_DATABASEscm \ -v /data/scm/mysql:/var/lib/mysql \ mysql:8.0 --character-set-serverutf8mb4参数说明-p把容器端口映射到宿主机必须和项目配置文件里的jdbc:mysql://localhost:3306/scm对齐-v把数据目录挂到宿主机防止容器重建后初始化脚本白跑utf8mb4是为了让课程名里的生僻字正常显示。演示前把这段命令写进 PPT 备注页现场如果数据库起不来照着敲一遍能救回整场答辩。启动完成后先用docker exec -it scm-mysql mysql -uroot -p确认五张核心表存在再去启动应用。5. 学生选课管理系统答辩PPT的现场收口演示脚本、日志证据与高频问答前面几章把内容做厚了最后这十分钟怎么讲决定了评委记住的是你的系统还是你的紧张。我一般会准备三样东西放在备注页一条最短演示路径、一份接口自测命令、一张高频问答表。它们平时看着不起眼现场出状况时全靠它们撑住。5.1 三分钟演示脚本只走一条最短路径演示不要从首页一路点到底选一条能覆盖核心逻辑的最短路径学生登录 → 查询课程 → 选中一门容量为 1 的课 → 选课成功 → 再次点击选课弹出重复选课提示 → 退课 → 容量恢复。这条路径同时覆盖了并发保护、唯一索引和状态流转三个技术点三分钟足够跑完。演示数据必须提前预置至少三个账号、一门容量为 1 的课程、一门与它时间冲突的课程。预置脚本写成 SQL 文件放在项目里演示前执行一次避免现场手输。5.2 高频问答把 java面试题 的思路用在答辩上答辩问答和 java面试题 的准备方式几乎一样都是「先给结论、再给依据、最后给边界」。下面这几条出现的概率最高。评委可能问的问题回答的落点并发选课怎么防止超选条件更新 SQL 版本号影响行数为 0 视为失败为什么不直接用悲观锁行锁持有时间长选课高峰会拖慢整体响应重复选课怎么拦数据库唯一索引兜底应用层只做友好提示冲突检测为什么放 SQL 里一次查询返回结果避免循环调用造成多次往返事务失败后容量会不会错乱扣减与写记录同事务异常统一回滚回答时不要一句「用了乐观锁」就停住把where version ?这行讲出来评委就知道你真写过。被问到不会的问题坦率说明当前方案的边界并给出替代思路比硬编一段要好。5.3 出错时的兜底用接口自测页代替现场点界面现场最怕的是前端页面白屏或者接口 500这时候不要反复刷新。提前在 PPT 备注里放一条自测命令用命令行验证后端是否正常能把问题快速定位到前端还是后端。# 直接调用选课接口观察返回码与提示信息绕开页面渲染问题 curl -X POST http://localhost:8080/api/selection \ -H Content-Type: application/json \ -d {studentId:1001,courseId:1,term:2024-2025-1}-X POST指定方法-H声明 JSON 类型-d传请求体三个参数一个都不能少否则后端会按表单解析报错。如果这条命令返回{code:1}说明后端链路完好问题出在页面如果直接返回 500看控制台堆栈里的第一条业务异常通常是数据库连接或者事务回滚相关的报错。把这条命令的返回结果截好图放进备注页评委临时加问「接口怎么测的」时连截图都不用现找。本文还有配套的精品资源点击获取