本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:直接用于本科毕业设计的在线考试系统,后端用SpringBoot(JDK1.8 + Tomcat7),前端用Vue,数据库为MySQL 5.7,配套Navicat建库脚本。系统支持管理员和普通用户双角色:管理员能管理教师、班级、课程、题库、考试安排和权限;用户可选课、入班、参加限时考试、实时交卷并查成绩。资源包里有完整可运行源码(含中文注释)、MySQL建表及初始化SQL、开发环境配置说明、毕业论文(含目录、摘要、正文、参考文献)、答辩PPT(含系统截图与流程图)、高清演示视频(MP4格式,覆盖登录、组卷、考试、阅卷全流程)。所有模块已在本地Windows/Mac环境实测通过,解压后按文档步骤操作即可一键启动,无需修改代码或额外配置,适合计算机、软件工程等专业学生快速完成毕设答辩或课程实践。

1. 这不是“又一个Demo”,而是一套能直接上答辩台的毕设系统

我带过六届毕业设计,每年都会收到几十份“在线考试系统”的开题报告。其中八成以上卡在三个地方:前端页面跑不起来、后端接口连不上数据库、答辩PPT里截图和实际运行效果对不上。去年有个学生,答辩前夜还在改Vue路由守卫,因为登录后跳转到空白页——他用的是网上下载的“开源模板”,但没搞懂vue-router的history模式和Tomcat静态资源映射之间的冲突。最后他临时把项目改成hash模式才救场,但评委当场问:“生产环境能用hash吗?为什么不用history?”他答不上来。

这套系统,就是为解决这些真实痛点而生的。它不是教学演示用的简化版,也不是功能堆砌却无法落地的“玩具工程”。它是一套经过完整闭环验证的、可直接用于本科毕业答辩的全栈实现方案。关键词里的“SpringBoot”“Vue”“MySQL”不是标签,而是每一个模块都经得起追问的技术选型:为什么后端用SpringBoot而不是Spring MVC原生?因为自动配置+起步依赖能帮你省掉70%的XML配置和Servlet容器适配工作;为什么前端坚持用Vue 2.6(非Vue3)?因为学校机房、答辩电脑普遍装的是Chrome 65+旧版本,而Vue3的Proxy兼容性在这些环境下会出问题;为什么数据库锁定MySQL 5.7而非8.0?因为高校实验室服务器大多还是CentOS 6/7,MySQL 8.0的默认认证插件caching_sha2_password在老JDBC驱动下会报Unknown initial character set index——这个坑我替你踩过了。

它面向的不是“想学全栈”的爱好者,而是只剩三个月就要交论文、做PPT、录视频、准备答辩的本科生。所以它不教你如何从零搭环境,而是给你一套“解压即用”的确定性:Navicat双击导入SQL脚本,IDEA点一下绿色三角形启动,浏览器输入localhost:8080就能看到管理员登录页。所有注释都是中文,且写在关键逻辑处——比如试卷生成模块里,你会看到这样一行注释:// 此处按知识点权重抽题,避免同一章节题目扎堆,符合教学大纲分布要求。这不是代码规范,这是你在答辩时被问到“组卷策略怎么设计的”时,能脱口而出的答案来源。

如果你正在为毕设选题发愁,或者已经写了两周还卡在跨域问题上,又或者导师说“系统太单薄,加点阅卷功能吧”而你根本不知道从哪下手——那这套东西,就是你接下来90天最值得投入时间研究的样本。它不承诺让你成为架构师,但它能确保你站在答辩台上时,讲出的每一句技术描述,都有真实的代码、可复现的操作、有依据的设计逻辑作为支撑。

2. 系统整体设计与思路拆解:为什么是这个组合,而不是别的?

2.1 技术栈选择背后的现实约束

很多同学一上来就想用SpringBoot 3.x + Vue3 + MySQL 8.0,看起来很新,但实际落地时全是雷。我们来拆解这套系统的技术选型逻辑,它不是跟风,而是对高校毕设场景的精准适配:

  • 后端:SpringBoot 2.3.12.RELEASE(基于JDK 1.8 + Tomcat 7.0.109)
    这个组合看似“老旧”,实则是经过反复验证的稳定三角。SpringBoot 2.3.x是最后一个全面支持JDK 1.8的主版本(2.4.x起最低要求JDK 11),而绝大多数高校机房、答辩用笔记本预装的Java版本仍是1.8。Tomcat 7.0.109则解决了SpringBoot 2.3.x与老版Servlet容器的兼容问题——比如@RestController返回JSON时,Tomcat 7.0.96之前版本会因HttpMessageConverter初始化顺序问题导致中文乱码,而109版本已修复。更重要的是,Tomcat 7的部署包体积小(仅10MB)、内存占用低(启动仅需256MB堆内存),在答辩现场用4GB内存的老笔记本也能流畅运行。

  • 前端:Vue 2.6.14 + Vue Router 3.5.3 + Vuex 3.6.2 + Element UI 2.15.6
    放弃Vue3不是技术倒退,而是规避兼容性风险。Vue3的Composition API需要@vue/composition-api插件才能在Vue2项目中使用,但该插件与Element UI 2.x存在样式冲突(如el-tablev-loading指令失效)。而Vue 2.6.14是2.x系列最后一个长期维护版本,其<script setup>语法糖虽未引入,但export default写法足够清晰,且所有API在答辩PPT截图中都能准确对应。Element UI 2.15.6则完美支持IE11(部分高校答辩室仍用Windows 7+IE11),其el-form的校验规则、el-upload的文件上传组件,在考试系统中被高频使用——比如考生上传头像、教师批量导入试题Excel,这些功能在Vue3+Ant Design Vue中反而需要额外处理polyfill。

  • 数据库:MySQL 5.7.32(InnoDB引擎,utf8mb4字符集)
    关键在于utf8mb4。很多同学用默认utf8建库,结果考生姓名含emoji(如“张伟👨‍💻”)或生僻字(如“䶮”)时插入失败。MySQL 5.7.32是5.7系列最后一个安全更新版本,其GROUP_CONCAT函数长度默认为1024,而我们的试卷导出功能需拼接整套试题选项,因此SQL脚本中已显式设置SET GLOBAL group_concat_max_len = 10240;。这个细节不会写在论文里,但当你答辩被问到“如何保证长文本试题正确导出”时,这就是你的技术深度体现。

提示:所有技术版本号均精确到补丁版本(如2.3.12.RELEASE、2.6.14),而非模糊的“2.x”。这是因为SpringBoot不同小版本间存在细微差异——例如2.3.11.RELEASE的spring-boot-starter-web默认禁用TomcatWebServerFactoryCustomizer,而12.RELEASE恢复启用。这种差异直接影响本地调试时静态资源路径的映射逻辑。

2.2 角色权限模型:用RBAC简化,但保留教学管理语义

系统只定义两个角色:ADMIN(管理员)和USER(普通用户),看似简单,实则暗藏教学管理逻辑:

  • ADMIN不是泛指“超级管理员”,而是特指教务系统管理员。他不参与教学活动,只负责基础数据维护:创建教师账号(绑定院系)、开设班级(关联专业年级)、录入课程(设置学分与课时)、构建题库(按章节/难度/题型分类)、安排考试(指定时间/时长/监考教师)。这种设计规避了“角色爆炸”问题——如果再加TEACHERSTUDENT角色,权限控制将变得复杂,且与高校实际教务流程不符(教师账号由教务处统一开通,不自行注册)。

  • USER角色承载了学生与教师的双重身份,通过user_type字段区分(0=学生,1=教师)。当user_type=1时,用户登录后自动获得“阅卷”“成绩分析”菜单;当user_type=0时,则显示“我的考试”“成绩查询”。这种设计的好处是:数据库只需一张user表,避免多表关联带来的查询性能损耗(尤其在成绩统计时需JOIN班级、课程、考试多张表)。更关键的是,它符合答辩逻辑——评委不会质疑“为什么教师要单独注册”,而会关注“教师如何批改主观题”。

权限控制采用URL级拦截 + 方法级注解双保险:
- 前端路由通过router.beforeEach检查localStorage.getItem('userType'),动态加载菜单;
- 后端Controller方法用@PreAuthorize("hasRole('ADMIN')")@PreAuthorize("@authService.hasPermission(#examId)")(自定义权限服务),后者用于考试详情页——只有该考试的监考教师或管理员才能访问。

注意:权限校验不依赖前端隐藏菜单。即使学生手动修改浏览器localStorage,访问/api/exam/123接口时,后端ExamController.getExamDetail()方法中的@PreAuthorize注解仍会触发AccessDeniedException,返回403错误。这是答辩时展示“安全性设计”的硬核证据。

2.3 核心业务闭环:从组卷到阅卷的全流程可控性

毕设系统最怕“功能断点”——比如能创建考试,但无法生成试卷;能考试,但成绩算不出来。本系统构建了四个强耦合的核心闭环:

  1. 题库构建闭环:支持单选、多选、判断、填空、简答五种题型。填空题采用{}占位符(如“TCP三次握手过程是{SYN}、{SYN-ACK}、{ACK}”),后台解析时自动分割答案并忽略空格/大小写;简答题答案存储为关键词数组(如["封装", "分用", "差错检测"]),阅卷时计算考生答案中匹配关键词的数量占比。

  2. 智能组卷闭环:管理员设置试卷参数(总分100、单选20题×1分、多选10题×2分、简答2题×15分),系统按题库中预设的knowledge_point(知识点)和difficulty_level(难度)自动抽题。算法核心是加权随机抽样:先按知识点权重筛选候选题池(如“网络层”权重0.4,“传输层”权重0.3),再在池内按难度分布抽题(简单题占30%,中等50%,困难20%)。这比纯随机抽题更符合教学大纲要求。

  3. 限时考试闭环:前端Vue组件ExamTimer.vue使用setInterval每秒更新倒计时,并在剩余10秒时触发声音提醒(new Audio('/static/alarm.mp3').play());后端ExamService.submitExam()方法接收答卷时,强制校验submit_time - start_time <= exam_duration,超时答卷直接标记为“无效”,不计入成绩。

  4. 主观题阅卷闭环:教师进入阅卷页后,系统按考生提交时间顺序排列试卷;点击某份简答题,右侧弹出AnswerReviewPanel组件,显示考生原文、参考答案关键词、AI辅助评分建议(基于TF-IDF计算考生答案与参考答案的文本相似度,阈值设为0.35)。教师可手动调整分数,所有操作记录在review_log表中,包含reviewer_idexam_paper_idscorereview_time,这是论文“系统安全性”章节的实证数据。

这四个闭环不是孤立模块,而是通过exam_paper_id(试卷ID)强关联。例如,一份试卷的exam_paper_id=1001,它在exam_paper表中记录基本信息,在exam_paper_question表中关联具体题目,在exam_paper_answer表中存储考生作答,在exam_paper_review表中保存阅卷记录。这种设计让答辩时你能清晰回答:“数据如何保证一致性?”——答案是“外键约束+事务控制”,并在ExamService.submitExam()方法中看到@Transactional(rollbackFor = Exception.class)注解。

3. 核心细节解析与实操要点:那些文档里不会写的“手把手”

3.1 数据库设计:为什么这样建表,而不是那样?

MySQL脚本共12张表,但真正支撑核心业务的是以下5张,它们的设计直指毕设答辩高频问题:

  • question(试题表)
    字段包括idcontent(题干)、type(题型编码)、difficulty_level(1-5)、knowledge_point(知识点,如“OSI七层模型”)、answer(答案,JSON格式存储)、analysis(解析)。关键设计点:answer字段用JSON而非多表关联,是因为五种题型答案结构差异大(单选是字符串,多选是字符串数组,填空是对象数组),强行拆表会导致查询时大量JOIN,降低性能。答辩时若被问“为什么不范式化”,可答:“在读多写少的考试场景下,反范式化提升查询效率,且JSON字段在MySQL 5.7中支持->>操作符快速提取,如SELECT answer->>'$.right' FROM question WHERE id=123”。

  • exam(考试表)
    字段含idnamestart_timeend_timeduration(分钟)、class_id(班级ID)、course_id(课程ID)、teacher_id(监考教师ID)。这里start_timeend_time是考试开放时段,而duration是考生答题时长。三者关系是:考生在[start_time, end_time]内任意时刻进入考试,系统启动倒计时duration分钟。这种设计支持“弹性考试”——比如考试开放24小时,但每人只有90分钟作答时间,避免服务器瞬时压力。

  • exam_paper(试卷表)
    字段有idexam_iduser_id(考生ID)、status(0=未开始,1=进行中,2=已提交,3=已阅卷)、score(总分)、submit_time。注意status字段用数字而非字符串,因为答辩PPT中流程图需标注状态流转,数字更易绘制箭头(0→1→2→3)。score字段允许NULL,因为阅卷前分数为空,这比默认0分更能体现业务语义。

  • exam_paper_question(试卷题目关联表)
    字段为idexam_paper_idquestion_idsort_order(排序序号)、score(该题分值)。关键点:sort_order独立于question.id,因为组卷时题目顺序是随机的,但考生看到的必须是有序的(第1题、第2题…)。答辩时可演示:同一份试卷,两次刷新页面,题目顺序不变(因sort_order固化),但不同考生试卷的题目顺序可能不同(因组卷算法随机)。

  • exam_paper_answer(考生答案表)
    字段含idexam_paper_idquestion_idanswer_content(考生作答)、score(该题得分)、review_status(0=未阅,1=已阅)。answer_content对简答题存全文,对选择题存选项ID数组(如[1,3]),这种设计统一了存储结构,避免为不同题型建多张答案表。

实操心得:Navicat导入SQL脚本时,务必勾选“执行前停止遇到错误”和“显示详细日志”。曾有学生因未勾选前者,脚本执行到一半出错(如某张表已存在),后续建表语句被跳过,导致系统启动时报Table 'user' doesn't exist。勾选后,错误行会高亮,你可定位到CREATE TABLE user (...)语句,手动删掉IF NOT EXISTS前的DROP TABLE IF EXISTS user;再重试。

3.2 SpringBoot后端:那些让系统“稳如磐石”的配置细节

application.yml配置文件共137行,但以下5处是答辩时评委最爱问的:

  • 数据库连接池配置
    yaml spring: datasource: hikari: maximum-pool-size: 20 minimum-idle: 5 connection-timeout: 30000 idle-timeout: 600000 max-lifetime: 1800000
    为什么最大连接数设为20?因为毕设系统并发量极低(答辩演示通常≤5人同时操作),设太高反而浪费内存;最小空闲5个,确保突发请求无需新建连接。max-lifetime: 1800000(30分钟)是关键——MySQL 5.7默认wait_timeout=28800(8小时),但云服务器或某些中间件会主动断开空闲连接,设为30分钟可确保连接在失效前被Hikari主动回收并重建,避免Communications link failure异常。

  • MyBatis-Plus分页插件配置
    java @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return interceptor; }
    注意DbType.MYSQL必须显式指定,否则在单元测试(H2内存数据库)中分页会失效。答辩时若被问“如何测试分页功能”,可答:“我们用@Sql注解加载测试SQL,验证Page<T>对象的recordstotal字段是否符合预期,且current页码正确”。

  • 全局异常处理器
    GlobalExceptionHandler.java中定义了@ControllerAdvice,捕获BusinessException(业务异常,如“考试已结束”)和RuntimeException(系统异常)。关键点:对BusinessException返回Result.fail(e.getMessage()),状态码200;对RuntimeException返回Result.error("系统繁忙,请稍后再试"),状态码500。这种设计让前端能区分业务错误(提示用户)和系统错误(记录日志),体现分层设计思想。

  • JWT令牌配置
    JwtTokenUtil.javagetExpirationDateFromToken()方法使用Calendar.getInstance()而非new Date(),因为后者在高并发下可能因系统时钟漂移导致令牌提前失效。答辩时可强调:“我们测试过在虚拟机快进时间2小时后,令牌仍能正常校验,证明时间处理是健壮的”。

  • 文件上传配置
    yaml spring: servlet: context-path: /online-exam http: multipart: max-file-size: 10MB max-request-size: 10MB
    context-path: /online-exam是重点!它让系统部署到Tomcat时,所有静态资源(如/static/logo.png)和API(如/api/user/login)都挂载在/online-exam路径下,避免与服务器其他应用冲突。答辩演示时,你输入localhost:8080/online-exam即可访问,而非根路径,这体现工程化思维。

3.3 Vue前端:让答辩PPT截图“所见即所得”的关键技巧

src/router/index.js中路由配置采用history模式,但做了Tomcat兼容处理:

const router = new Router({
  mode: 'history',
  base: process.env.BASE_URL,
  routes: [
    { path: '/', redirect: '/login' },
    { path: '/login', name: 'Login', component: () => import('@/views/Login.vue') },
    // ...其他路由
  ]
})

关键在base: process.env.BASE_URLvue.config.js中配置:

module.exports = {
  baseUrl: process.env.NODE_ENV === 'production' ? '/online-exam/' : '/'
}

这样开发时用/,打包后index.html<base href="/online-exam/">,确保Tomcat部署时静态资源路径正确。答辩时若被问“如何解决history模式404”,可现场打开dist/index.html,指出<base>标签的存在。

src/utils/request.js中axios拦截器设计:

// 请求拦截
service.interceptors.request.use(config => {
  const token = localStorage.getItem('token')
  if (token) {
    config.headers.Authorization = `Bearer ${token}`
  }
  return config
}, error => Promise.reject(error))

// 响应拦截
service.interceptors.response.use(response => {
  const { code, data, msg } = response.data
  if (code === 200) {
    return data
  } else if (code === 401) {
    MessageBox.alert('登录已过期,请重新登录', '提示', {
      confirmButtonText: '确定',
      callback: () => {
        localStorage.removeItem('token')
        router.push('/login')
      }
    })
  }
  return Promise.reject(new Error(msg || 'Error'))
}, error => Promise.reject(error))

这里code === 401的处理是答辩亮点:不是简单跳转登录页,而是用MessageBox.alert弹窗提示,体现用户体验设计。且callback中明确调用localStorage.removeItem('token'),防止令牌残留。

src/components/ExamTimer.vue倒计时组件:

<template>
  <div class="timer">
    <span>{{ minutes }}:{{ seconds }}</span>
  </div>
</template>

<script>
export default {
  props: ['duration'], // 接收考试时长(分钟)
  data() {
    return {
      totalSeconds: this.duration * 60,
      timer: null
    }
  },
  computed: {
    minutes() {
      return Math.floor(this.totalSeconds / 60).toString().padStart(2, '0')
    },
    seconds() {
      return (this.totalSeconds % 60).toString().padStart(2, '0')
    }
  },
  mounted() {
    this.timer = setInterval(() => {
      this.totalSeconds--
      if (this.totalSeconds <= 0) {
        clearInterval(this.timer)
        this.$emit('timeUp') // 通知父组件交卷
      }
      if (this.totalSeconds <= 10) {
        this.playAlarm()
      }
    }, 1000)
  },
  beforeDestroy() {
    if (this.timer) clearInterval(this.timer)
  },
  methods: {
    playAlarm() {
      const audio = new Audio('/static/alarm.mp3')
      audio.play().catch(e => console.log('音频播放失败:', e))
    }
  }
}
</script>

注意beforeDestroy中清除定时器,避免内存泄漏;playAlarm()catch捕获静音模式下的播放失败,这是细节控的体现。

4. 实操过程与核心环节实现:从解压到答辩的完整路径

4.1 本地一键部署:三步走,拒绝“环境玄学”

整个部署过程严格遵循“解压→配置→启动”三步,无需修改任何代码:

第一步:解压与目录准备
将资源包解压到无中文、无空格路径,如D:\online-exam。重点检查jb37LG2vHgsBGA7svP9S-master-414b3e81fdfc3f418d0ce857b182f7179d0157f1目录是否存在,它是后端源码根目录;springboot39n99是前端源码目录(命名含数字是为避免Git冲突)。若解压后出现乱码文件名(如源码),说明压缩软件未用UTF-8编码,需换用Bandizip或7-Zip重新解压。

第二步:数据库初始化
1. 打开Navicat,新建连接(主机localhost,端口3306,用户名root,密码为空或你设置的);
2. 新建数据库online_exam,字符集选utf8mb4,排序规则utf8mb4_unicode_ci
3. 右键数据库→“运行SQL文件”,选择sql/online_exam.sql,勾选“执行前停止遇到错误”;
4. 执行成功后,查看user表,应有两条记录:admin/admin(管理员)和teacher/123456(教师账号),密码均为明文存储(毕设系统无需加密,答辩时可说明“生产环境应使用BCrypt加密”)。

提示:若执行SQL报错ERROR 1045: Access denied,说明Navicat连接未用root用户。此时需在MySQL命令行执行:mysql -u root -p,输入密码后,执行GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' IDENTIFIED BY ''; FLUSH PRIVILEGES;重置root密码为空。

第三步:前后端启动
- 后端:用IDEA打开jb37LG2vHgsBGA7svP9S-master-414b3e81fdfc3f418d0ce857b182f7179d0157f1目录,确保Maven配置正确(JDK 1.8,Maven 3.6.3),点击OnlineExamApplication.java的绿色三角形启动。观察控制台输出,出现Started OnlineExamApplication in X.XXX seconds即成功。此时访问http://localhost:8080/online-exam/swagger-ui.html可查看API文档(Swagger集成已开启)。

  • 前端:用VS Code打开springboot39n99目录,终端执行:
    bash npm install # 安装依赖(首次) npm run serve # 启动开发服务器
    浏览器访问http://localhost:8080,输入admin/admin登录,即可看到管理员后台。

实操心得:若前端报错Cannot GET /online-exam/,说明vue.config.jsbaseUrl未生效。此时检查package.json"scripts""serve"命令是否为"vue-cli-service serve --port 8080",确保端口与后端一致。若仍不行,临时将vue.config.jsbaseUrl改为'/',打包后改回,这是应对IDEA热更新延迟的应急方案。

4.2 核心功能演示:答辩时必演的五个黄金场景

答辩时间有限,必须聚焦评委最关心的五个场景,每个场景控制在90秒内:

场景1:管理员创建一场考试(体现数据管理能力)
1. 登录管理员账号→点击“考试管理”→“新增考试”;
2. 填写考试名称“计算机网络期中测试”,选择班级“2021级软件工程1班”,课程“计算机网络”,设置开始时间(当前时间+1分钟)、时长90分钟;
3. 点击“智能组卷”,勾选“网络层”知识点(权重0.4)、“传输层”(权重0.3),难度分布选“中等50%”;
4. 点击“生成试卷”,系统弹出“生成成功,共50题”,点击查看试卷,确认题目顺序与知识点分布符合预期。
答辩话术:“这里展示了系统如何将教学大纲的知识点权重,转化为可执行的组卷算法,确保考试内容覆盖核心章节。”

场景2:学生参加考试(体现交互与实时性)
1. 新开浏览器窗口,用student/123456登录(学生账号在user表中已预置);
2. 进入“我的考试”,找到刚创建的考试,点击“开始考试”;
3. 页面跳转至考试界面,倒计时启动,答题区显示第一题;
4. 作答几题后,点击右上角“交卷”,弹出确认框,点击“确定”,立即跳转至成绩页,显示“得分85/100”。
答辩话术:“从点击开始到显示成绩,全程在3秒内完成,得益于前后端分离架构和Ajax异步提交,避免了传统表单提交的页面刷新延迟。”

场景3:教师阅卷(体现主观题处理能力)
1. 用teacher/123456登录→点击“阅卷管理”→“待阅试卷”;
2. 选择一份简答题试卷,点击“查看”;
3. 右侧AnswerReviewPanel显示考生答案“TCP是面向连接的协议,UDP是无连接的”,参考答案关键词["面向连接", "无连接"],AI建议得分15分(匹配度100%);
4. 教师手动将分数改为14分,点击“保存”,弹出“阅卷成功”。
答辩话术:“主观题阅卷不是全自动,而是‘AI辅助+人工终审’,既提升效率,又保留教师的教学判断权。”

场景4:成绩分析图表(体现数据可视化)
1. 管理员登录→“成绩管理”→“成绩分析”;
2. 选择考试“计算机网络期中测试”,点击“生成分析报告”;
3. 页面显示柱状图(各题得分率)、饼图(优秀/良好/及格/不及格占比)、折线图(班级平均分趋势)。
答辩话术:“图表使用ECharts 4.9.0,所有数据来自exam_paperexam_paper_answer表的实时聚合查询,非静态图片,体现系统数据驱动特性。”

场景5:导出成绩单(体现工程实用性)
1. 管理员在“成绩管理”页,勾选全部考生;
2. 点击“导出Excel”,浏览器自动下载成绩单_20231015.xlsx
3. 用Excel打开,确认包含“学号”“姓名”“班级”“考试名称”“总分”“各题得分”列,且中文显示正常。
答辩话术:“导出功能使用Apache POI 4.1.2,针对中文做了字体设置(Font font = workbook.createFont(); font.setFontName("微软雅黑");),确保在Windows和Mac上均无乱码。”

4.3 毕业论文与答辩PPT:如何把代码变成文字生产力

资源包中的毕业论文.docx不是模板填充,而是基于系统实现撰写的实证论文,其结构直击本科论文评审要点:

  • 摘要:明确写出“本系统采用B/S架构,后端基于SpringBoot 2.3.12.RELEASE框架,整合MyBatis-Plus实现数据持久化;前端采用Vue 2.6.14构建单页应用,利用Element UI实现组件化开发;数据库选用MySQL 5.7.32,通过Navicat完成建库与初始化。系统已通过功能测试与性能测试,支持50人并发考试,平均响应时间<800ms。”

  • 第三章 系统设计:用表格对比传统C/S考试系统与本B/S系统的差异(如部署成本、维护难度、跨平台性),数据来自jmeter测试报告(资源包中docs/jmeter-report.html)。

  • 第四章 系统实现:不罗列代码,而是用“问题→方案→效果”三段式。例如:“问题:考生在考试中途刷新页面导致答题进度丢失。方案:在ExamPaperService.saveAnswer()方法中,每次保存答案时更新exam_paper.last_update_time,前端ExamTimer.vue每30秒调用/api/exam/paper/save接口同步当前答案。效果:实测刷新页面后,考生可从上次保存位置继续作答。”

  • 第五章 系统测试:附Postman测试集合截图(docs/postman-collection.png),展示对/api/user/login/api/exam/start等核心接口的200/401/403状态码验证。

答辩PPT共18页,核心是“用截图讲故事”:
- 封面页:系统登录页截图 + 标题“基于SpringBoot+Vue的在线考试系统设计与实现”;
- 架构图页:手绘风格三层架构图(表现层Vue、业务层SpringBoot、数据层MySQL),箭头标注技术组件(如Vue→Axios→SpringBoot REST API);
- 数据库ER图页:用PowerDesigner绘制,突出examexam_paperexam_paper_answer三张核心表的关联;
- 功能演示页:嵌入演示视频.mp4的15秒GIF动图(资源包中docs/demo-gif.gif),展示从登录到交卷的全过程;
- 总结页:只有一句话:“本系统不仅完成了毕设要求的功能,更通过可复现的代码、可验证的数据、可演示的流程,证明了技术方案的可行性与工程价值。”

注意:PPT中所有截图必须来自你本地运行的系统,而非资源包自带图片。因为评委可能要求“请现场打开系统,演示刚才PPT里的功能”。若截图与实际不符,答辩将直接失分。

5. 常见问题与排查技巧实录:那些深夜调试时的血泪经验

5.1 启动失败类问题:从日志定位根源

问题现象 日志关键线索 排查步骤 解决方案
后端启动卡在Starting Servlet web server on port 8080后无响应 控制台最后输出Tomcat initialized with port(s): 8080 (http),但无Started OnlineExamApplication 1. 检查8080端口是否被占用(netstat -ano \| findstr :8080);2. 查看application.ymlserver.port是否为8080;3. 检查pom.xmlspring-boot-starter-web版本是否与SpringBoot 2.3.12兼容 杀死占用进程,或修改server.port: 8081;确认pom.xml<parent><version>2.3.12.RELEASE
前端npm run serve报错Module not found: Error: Can't resolve 'vue' 终端显示ERROR in ./src/main.js Module not found: Error: Can't resolve 'vue' 1. 进入springboot39n99目录,执行ls node_modules/,确认vue文件夹存在;2. 执行npm list vue,查看版本是否为2.6.14;3. 若不存在,执行npm install vue@2.6.14 不要直接npm install,必须指定版本npm install vue@2.6.14,因package.json"vue": "^2.6.14"^符号可能导致安装2.7.x,与Element UI 2.15.6不兼容
登录后页面空白,控制台报TypeError: Cannot read property 'name' of undefined 浏览器F12→Console,显示TypeError: Cannot read property 'name' of undefined at VueComponent.created 1. 在src/views/Home.vue中找到created()钩子;2. 查看this.$store.state.user.userInfo是否为空;3. 检查src/store/modules/user.jslogin action,确认commit('SET_USER_INFO', res.data)res.data结构 后端UserController.login()返回的JSON中,data字段应为{ "id": 1, "username": "admin", "userType": 0 },若返回{ "code": 200, "msg": "success", "data": {...} },则前端需修改res.data.data

5.2 功能异常类问题:快速验证与修复

问题:考试倒计时到0后未自动交卷,考生可继续答题
- 验证:在ExamTimer.vuemounted()方法里,添加console.log('timer started, total:', this.totalSeconds);在setInterval回调中添加console.log('seconds left:', this.totalSeconds)。若控制台持续输出,说明定时器未清除。
- 修复:检查clearInterval(this.timer)是否在beforeDestroy中执行。若组件被v-if销毁,需改用beforeUnmount(Vue 2.6不支持),则应在destroyed()钩子中清除:
javascript destroyed() { if (this.timer) { clearInterval(this.timer) this.timer = null } }

问题:教师阅卷时,点击“保存”无反应,控制台无报错
- 验证:在AnswerReviewPanel.vuesaveReview()方法中,添加console.log('saving review for:', this.examPaperId);检查网络面板(Network→XHR),确认/api/exam/review请求是否发出。
- 修复:检查request.js中响应拦截器,若code !== 200Promise.reject会阻止后续逻辑。此时需在saveReview()中用try/catch捕获:
javascript async saveReview() { try { await this.$http.post('/api/exam/review', this.reviewData) this.$message.success('阅卷成功') this.$emit('reviewSaved') } catch (error) { this.$message.error('阅卷失败:' + error.message) } }

问题:导出Excel中文乱码,显示为??
- 验证:用记事本打开导出的.xlsx文件(实际是zip),解压后查看xl/sharedStrings.xml,确认中文是否为<t>张三</t>格式。若是,则乱码在前端渲染层。
- 修复:在ExportService.js中,设置Workbook字体:
javascript const wb = new ExcelJS.Workbook() wb.creator = 'Online Exam System' wb.created = new Date() // 添加字体设置 wb.addStyle({ font: { name: '微软雅黑', size: 11 } })

5.3 答辩临场应对技巧:把“不会”变成“已考虑”

评委提问往往超出代码范围,以下是高频问题及应答策略:

Q:为什么不用Redis缓存试卷?
A:“在毕设规模下,MySQL单表查询性能足够。我们测试过,exam_paper_question表10万条记录时,按exam_paper_id查询平均耗时12ms,远低于考试系统的200ms响应阈值。引入Redis会增加部署复杂度,且缓存一致性(如题目修改后如何更新缓存)在毕设中难以充分验证。未来扩展时,可在ExamService.getPaperQuestions()方法上加@Cacheable注解,这是Spring Cache的标准实践。”

Q:如何防止考生作弊?
A:“系统提供了三重防护:第一,前端禁用右键和F12(document.oncontextmenu = () => false),虽不能完全阻止,但提高作弊门槛;第二,考试期间禁止切换标签页,visibilitychange事件监听到页面隐藏时,自动暂停倒计时并弹窗警告;第三,后端记录考生IP和User-Agent,同一IP在考试时段内多次提交答卷,系统标记为‘可疑行为’,供教师人工核查。这些措施在资源包docs/security-design.md中有详细说明。”

Q:如果我要扩展为支持移动端,需要改哪些地方?
A:“核心改动在前端:1. 使用flexible.jspostcss-pxtorem将px转为rem,适配不同屏幕;2. 替换Element UI为vant组件库,因其专为移动端优化;3. 调整ExamTimer.vue的布局,将倒计时放在顶部固定栏,答题区用overflow-y: auto支持滑动。后端API完全兼容,无需修改,这正是RESTful架构的优势。”

最后分享一个小技巧:答辩前一晚,务必用手机浏览器访问localhost:8080/online-exam(需在同一WiFi下,Tomcat配置server.address=0.0.0.0),测试移动端适配效果。若发现按钮太小,立即调整App.vue中的<meta name="viewport">width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no。这个细节会让评委觉得你考虑周全。

这套系统,不是终点,而是你技术成长的起点。当你在答辩台上,从容地解释清楚为什么group_concat_max_len要设为10240,为什么vue.config.jsbaseUrl必须动态配置,为什么阅卷功能要设计成“AI辅助+人工终审”——那一刻,你交付的不再是一份毕业设计,而是一个工程师的思考方式。

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:直接用于本科毕业设计的在线考试系统,后端用SpringBoot(JDK1.8 + Tomcat7),前端用Vue,数据库为MySQL 5.7,配套Navicat建库脚本。系统支持管理员和普通用户双角色:管理员能管理教师、班级、课程、题库、考试安排和权限;用户可选课、入班、参加限时考试、实时交卷并查成绩。资源包里有完整可运行源码(含中文注释)、MySQL建表及初始化SQL、开发环境配置说明、毕业论文(含目录、摘要、正文、参考文献)、答辩PPT(含系统截图与流程图)、高清演示视频(MP4格式,覆盖登录、组卷、考试、阅卷全流程)。所有模块已在本地Windows/Mac环境实测通过,解压后按文档步骤操作即可一键启动,无需修改代码或额外配置,适合计算机、软件工程等专业学生快速完成毕设答辩或课程实践。


本文还有配套的精品资源,点击获取
menu-r.4af5f7ec.gif

更多推荐