简介基于SpringBoot的在线考试系统是一套面向毕业设计场景的完整项目资源。系统包含管理员与用户两种角色前台设有首页、试卷表、公告、课程、个人中心后台分为用户端与管理员端分别支持个人中心、公告管理、课程管理、考试管理以及基础数据管理等功能覆盖从考试安排、在线答题到成绩查看的完整业务链路。资源包共3个文件内含源码压缩包、MySQL数据库脚本和说明文档整体大小24.12MB文件少而精导入开发环境后即可对照运行。压缩包中另附配套报告梳理了系统需求分析、数据库设计及前后台实现思路有助于快速掌握项目结构并在此基础上进行二次开发。目前已有58人学习下载可作毕业设计、Spring Boot Web开发练习或在线考试类课题的参考方案。1. 在线考试系统在毕业设计里为什么总被翻车先说清这份源码能解决什么每年毕设季都能看到一批做在线考试系统的同学选题撞车不可怕可怕的是撞了车还都卡在同一个位置后端起不来、数据库连不上、交卷算分对不上。你去找学长要源码他发你一个十几兆的压缩包解压之后全是报错问一句“你JDK什么版本”你就答不上来。这份基于SpringBoot的在线考试系统源码数据库报告就是冲着“能跑通、能看懂、能答辩”这三个诉求来的。它不是一个空壳项目包含完整的后端工程、初始化数据库脚本和一份设计报告覆盖学生端考试、教师端出题、管理员管理用户这几个核心闭环。适合三类人第一类是拿它当毕设底子准备二次开发的第二类是SpringBoot刚入门想找一个完整前后端项目练手的第三类是时间紧需要一份能讲清楚设计思路的报告来支撑答辩的。你拿到的不是代码堆是一条能走通的业务链路。2. 从ER图到数据表先把题库、试卷、考试、成绩四张核心表的结构看懂拿到源码先别急着启动第一件事是打开数据库脚本把表结构读懂。在线考试系统的数据模型并不复杂但表与表之间的关系如果没理清后面改业务逻辑的时候会处处踩坑。这份资源的SQL脚本里核心业务表可以归成四类用户体系、题库与试卷、考试过程、成绩结果。2.1 四张核心表的关系为什么成绩表要单独建用户体系一般是一张学生表加一张教师表或者用一张带角色的用户表统一管理。我拆过的在线考试项目里大多数会用一张user表加role字段来区分角色这样登录校验和权限拦截都好写。题库表存放题目内容、选项、正确答案、所属课程和难度等级试卷表有两种设计方式一种是把试卷定义成一张表另一种是试卷加试卷题目关联表后者更灵活支持随机组卷。考试过程的核心是考试记录表每次学生开始考试就生成一条记录记录考试时间、状态和最终得分。成绩表单独建的好处是你可以把成绩和考试记录解耦——学生可以查历史成绩教师可以按课程统计平均分而不需要去翻每一场考试的明细。如果成绩数据直接写在考试记录表里后期做数据分析时写SQL就会很别扭。表名核心字段作用userid, username, password, role登录认证与权限区分questionid, course_id, type, content, answer题库基础数据examid, title, duration, question_ids试卷定义与组卷范围exam_recordid, user_id, exam_id, status, score考试过程与结果记录scoreid, user_id, exam_id, score, create_time成绩归档与后续统计设计报告里如果配有ER图你把它和这几张表的字段对着看能省很多理解时间。拿到SQL脚本后我建议先用Navicat或DataGrip打开把外键关系捋一遍再开始动代码。2.2 建库脚本与初始化数据跑通项目前先确认三件事大部分毕设项目的SQL脚本都能直接导入但导入前要确认三件事MySQL版本、字符集、是否自带初始化数据。这份资源的脚本里应该包含建库语句、建表语句和演示数据演示数据非常关键没有它你登录界面都进不去。CREATE DATABASE IF NOT EXISTS exam_system DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE exam_system; CREATE TABLE user ( id int(11) NOT NULL AUTO_INCREMENT, username varchar(50) NOT NULL, password varchar(255) NOT NULL, role tinyint(4) DEFAULT 2 COMMENT 1:管理员 2:学生 3:教师, create_time datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY uk_username (username) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; INSERT INTO user (username, password, role) VALUES (admin, e10adc3949ba59abbe56e057f20f883e, 1);这段建表脚本里有一个容易被忽略的细节password字段存的是MD5加密后的值演示账号admin的密码是123456加密后的结果你直接用SQL去查会看到一串看不懂的字符串这是正常现象。角色字段用tinyint而不是字符串是为了查询效率但阅读性差一点你可以在设计报告里解释为“用数字枚举表示角色状态”。初始化数据里一般会包含几个测试账号、一个班级的题库数据、一张测试试卷。导入之后先查一下user表有没有数据exam表有没有试卷这两张表有数据系统才有跑起来的前提。如果脚本执行报错大概率是MySQL版本兼容性问题后面避坑章节会专门说。3. 把SpringBoot后端跑起来配置项、启动顺序和第一个接口验证数据库就绪之后进入后端启动环节。SpringBoot项目跑不起来八成不是代码问题而是环境或配置问题。这个项目涉及JDK版本、Maven依赖、数据库连接、端口占用四个变量任何一个不对都会报错。我建议按下面这个顺序来操作。3.1 application.yml里最常改的三个配置项打开src/main/resources下的application.yml这是整个后端的入口配置。你不需要理解每一行但必须知道哪几个配置直接影响启动成败。server: port: 8081 spring: datasource: url: jdbc:mysql://localhost:3306/exam_system?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/Shanghai username: root password: yourpassword driver-class-name: com.mysql.cj.jdbc.Driver mybatis: mapper-locations: classpath:mapper/*.xml type-aliases-package: com.example.exam.entity这里最容易被坑的是端口。很多同学本机8080端口已经被其他服务占用启动的时候日志会报Port already in use但因为是最后一行报错你往往先看到的是前面的Spring Logo。把端口改成8081或8888能避开大部分冲突。数据库密码必须改成你本机MySQL的真实密码否则报错信息里会出现Access denied for user。MyBatis的mapper-locations配置决定框架去哪里找SQL映射文件。如果你发现某个接口报“Invalid bound statement (not found)”优先检查这个路径和实际包结构是否一致。同理type-aliases-package要对应你实体类所在的包名不一致会导致启动时扫描不到别名。3.2 接口请求链路怎么走通从登录到获取试卷后端启动成功后会监听配置的端口接下来用Postman或浏览器验证接口链路。一个正常的在线考试系统核心接口顺序是登录获取Token、根据课程获取试卷、提交答案、查询成绩。以登录接口为例它接收用户名和密码返回一个Token用于后续请求的鉴权。curl -X POST http://localhost:8081/api/user/login \ -H Content-Type: application/json \ -d {username:student01,password:123456}如果你看到返回的JSON里包含token或类似字段说明认证链路是通的。这个项目的登录逻辑大致是接收参数、查询数据库、比对加密后的密码、生成Token返回前端。Token的生成方案常见的有JWT和Redis存储两种具体看源码里用的哪一种设计报告中会写清楚。验证登录之后再请求试卷列表接口看一下返回的数据结构里是否包含题目列表。如果试卷数据是空的排查方向在数据库的exam表数据是否导入成功而不是后端代码。按这个顺序走完你至少能确认三条链路正常用户认证、数据查询、JSON序列化。3.3 前端页面和接口的对应关系怎么核对这份资源如果带了前端页面不管是用Thymeleaf模板还是Vue静态页你都需要建立“页面元素→接口→数据库表”的对应关系。最笨但最有效的方法是打开浏览器开发者工具切到Network面板点一下页面上的按钮看发出的请求路径和参数。比如学生点击“开始考试”按钮浏览器会发一个请求路径里通常带有examId参数。然后你回到后端代码里搜索这个路径就能找到对应的Controller方法再往里看Service层是怎么调用Mapper的。我见过太多人拿着源码却只会改个页面标题一问到“这个按钮的数据从哪来的”就卡住。你把三个请求走通答辩的时候老师问什么你都能接上。4. 避坑在线考试系统最容易翻车的五个地方这个项目我前后在不同机器上跑过几遍也见过不少同学卡在同一个位置。下面这几条是典型的翻车现场按“现象→原因→解决”的格式整理你遇到类似问题直接对照排查。4.1 登录接口报错但控制台没有业务日志现象点击登录按钮前端提示系统异常后端控制台只打印一段大堆栈看不到具体的业务错误。原因数据库连接失败是常见原因或者密码字段比对出现空指针。解决在登录方法第一行加一个日志输出打印传入的参数再用Postman单测登录接口绕过前端看后端返回。4.2 交卷后成绩显示为0现象学生提交试卷后考试成绩一直是0但考试记录的状态已经是已完成。原因成绩计算环节没有执行成功可能是得分逻辑中获取标准答案时拿不到数据或者算分代码被异常中断try-catch吞掉了错误。解决查看算分服务里有没有try-catch块如果有把e.printStackTrace()改成日志输出或者临时注释掉catch让异常抛出来。4.3 考试时间到了还能继续答题现象页面倒计时结束但学生还能提交答案后端也正常接收。原因倒计时只在前端控制提交接口没有校验考试时长。解决后端在交卷接口里根据考试记录的开始时间和试卷设定的时长做校验超过时间直接拒绝提交。这也是答辩时老师常问的一个扩展点你答上来会加分。4.4 数据库导入脚本报语法错误现象把SQL文件导入到MySQL时提示版本相关的语法错误或者字符集错误。原因脚本是在MySQL 8.0环境写的你本机用的是MySQL 5.7导致某些语法不兼容或者导入时没有执行USE语句。解决先确定本机MySQL版本如果你用的是5.7就把脚本里的utf8mb4相关语句保留但把默认字符集改掉或者直接用命令行source方式导入不要用图形工具复制粘贴。4.5 启动时报端口占用或JDK版本不匹配现象启动时第一屏Spring Logo还没出来就提示端口被占用或者编译时报UnsupportedClassVersionError。原因端口占用是8080被其他程序占用版本不匹配是你用的JDK版本和项目中Maven的编译版本不一致。解决启动前用netstat命令查端口占用或者直接改application.yml的端口JDK版本建议统一为JDK 8或11具体看项目pom.xml里maven.compiler.source的配置值。5. 把项目改成你自己的毕设角色权限、随机组卷和防作弊的三个扩展点源码跑通只是第一步毕设答辩要拿高分你得在原项目上加东西。这里我推荐三个改动量小但很能体现思考的扩展点都是在线考试系统里老师爱问的方向。5.1 角色权限统一拦截器和注解鉴权怎么选原项目的权限逻辑如果只是简单判断session里有没有用户那是一个很薄的安全层。你可以改成基于拦截器加自定义注解的方式代码量不大但结构看起来专业很多。具体做法是定义一个角色注解在Controller的方法上标注允许访问的角色然后写一个拦截器统一校验。Target(ElementType.METHOD) Retention(RetentionPolicy.RUNTIME) public interface RequireRole { String value() default student; }在拦截器里通过HandlerMethod拿到方法上的注解再对当前登录用户的角色做比对。这样一个注解加一个拦截器就能替代散落在各个方法里的重复判断。这个设计在答辩时很好讲因为你能说清楚“鉴权逻辑集中管理”这个设计思想。5.2 随机组卷从题库里按类型抽题的两种实现大部分毕设的试卷是提前配好的固定试卷你可以改成“每次进入考试时从题库随机抽题”。实现方式有两种第一种是用SQL的ORDER BY RAND()简单但性能一般适合题库数据量几千条以内的场景第二种是用代码逻辑先查题型分布再按比例从每个题型里随机选题可控性更强。// 从题库中按题型随机抽取题目 ListQuestion questions questionMapper.selectByType(type); Collections.shuffle(questions); ListQuestion selected questions.subList(0, Math.min(count, questions.size()));这段代码的逻辑是先从数据库取出某个题型下的全部题目再用Collections.shuffle打乱顺序最后截取需要的数量。参数count是抽题数量你需要根据试卷的题型结构提前算好每个题型抽几道。用这种方式比直接写ORDER BY RAND()更容易控制难度分布比如简单题40%、中等题40%、难题20%。5.3 前端防作弊切屏检测与交卷时间校验在线考试系统老师最喜欢问的问题就是“怎么防止学生作弊”。你不需要做摄像头监控那种大工程做一个切屏检测就够了监听浏览器的visibilitychange事件记录切屏次数超过N次强制交卷。同时在后端也做一道时间校验防止前端篡改时间。document.addEventListener(visibilitychange, function() { if (document.hidden) { let count localStorage.getItem(switchCount) || 0; count; localStorage.setItem(switchCount, count); if (count 3) { alert(切屏次数过多考试将被强制提交); submitExam(); } } });这个方案虽然简单但体现了“前端提示、后端校验”的双层思路。你还可以把切屏次数这个字段写入考试记录表答辩时展示给老师看比单纯说“我做了防作弊”有说服力得多。6. 验收不是能跑就行用三个用例把核心流程走穿拿到源码后建议不要直接写报告先按我下面这套流程在本地完整走一遍。我把这套流程叫“三层验收”每一层对应一个必测的闭环走完才算真正把这个系统接收了。用例操作步骤预期结果对应模块学生考试闭环学生登录→进入考试→作答→交卷→查看成绩成绩正确显示考试与成绩模块教师管理闭环教师登录→新增题目→创建试卷→查看考试统计题目入库、试卷生成题库与试卷模块管理员管理闭环管理员登录→新增用户→禁用用户→重置密码用户状态改变用户管理模块第一个用例是最重要的。你会发现很多隐藏bug都在交卷瞬间出现比如成绩不对、页面跳转失败。第二个用例验证题库这块“数据进口”是否畅通如果教师不能新增题目那整个组卷功能就是摆设。第三个用例验证权限边界是否生效普通学生账号调用管理接口是否被拒绝。每个用例跑完打开后端日志看一眼有没有异常堆栈。很多项目表面功能正常日志里已经刷了半屏报错。如果发现问题优先看是不是空指针或数组越界这两种异常在在线考试系统里出现频率最高。我把这套验收流程固定在每次拿到毕设源码后的第一个小时里执行。先跑学生闭环再跑教师闭环最后用管理员账号收尾。这三条链路通了这个项目才算真正到我手里。希望你也能在答辩前把这条链路走穿与其在台上被老师问倒不如在台下先把系统跑透。希望帮到你。本文还有配套的精品资源点击获取