ARTICLE DETAIL

资讯详情

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

SpringBoot+Vue+MySQL在线考试系统源码详解与部署实践

SpringBoot+Vue+MySQL在线考试系统源码详解与部署实践 做在线考试系统这几年我发现一个特别有意思的现象市面上能找到的开源考试系统源码要么年代久远、技术栈陈旧到没法用要么就是阉割版下载下来根本跑不起来。真正能拿来即用、前后端分离、还能支撑起一个真实教学场景的完整项目其实相当稀缺。所以当我看到这套SpringBoot Vue MySQL的在线考试系统源码时第一反应是这个东西值得好好拆解一遍。它不仅覆盖了考试系统的核心业务闭环——从题库维护、试卷生成、在线答题到自动阅卷、成绩统计——而且技术栈是目前国内中小型项目最主流的三件套特别适合作为毕业设计参考、企业内部培训系统二次开发底座或者初学者做项目实战练手的完整范例。这篇文章我会从业务需求、数据库建模、后端接口设计、前端页面实现到部署运行把这套系统的核心设计思路和几个容易踩坑的细节全部讲透。1. 项目整体设计与技术选型思路1.1 为什么是SpringBoot Vue MySQL这个组合先说选型。在线考试系统这种业务系统核心诉求无非是开发效率要高、业务逻辑要清晰、部署要简单、并发要求不至于太夸张。SpringBoot Vue MySQL这套组合恰好精准命中这些点。后端用SpringBoot本质上是看中了它约定大于配置的特性。考试系统里涉及的模块不算少——用户权限、题库管理、试卷生成、考试发布、答案提交、自动评分、成绩查询如果裸用SSMSpring SpringMVC MyBatis光XML配置和Bean装配就能耗掉两三天时间。SpringBoot内嵌Tomcat、自动配置数据源、一键打包成可执行Jar部署成本趋近于零这在答辩演示或者私有化部署场景里是巨大的优势。前端选Vue道理也很直白。考试系统的交互虽然不算特别复杂但管理端题库维护、试卷配置和考生端答题、倒计时、交卷是两个完全不同的交互逻辑。用Vue组件化开发可以把题目卡片、倒计时组件、分页组件这些复用单元单独抽出来管理端和考生端各自组合维护起来远比传统的jQuery拼DOM舒服。而且Vue生态里的Element UI组件库对管理系统这类场景的覆盖度非常好表格、表单、弹窗这些高频UI组件几乎开箱即用。MySQL作为数据库选择就不用多解释了。考试系统的数据模型是典型的关系型结构用户、题目、试卷、考试、答题记录、成绩这些实体之间外键关系明确用MySQL管理事务和保证数据一致性正当其位。对于中小规模场景——几千学生、几万道题目、同时在线考试人数几百人这个量级——MySQL配上合理的索引和连接池配置性能完全扛得住。1.2 系统的整体角色与业务闭环在动笔写代码之前先把系统的角色边界理清楚这一步比什么都重要。我见过太多半成品的考试系统代码写得花里胡哨结果连谁能组卷、谁能阅卷、成绩谁来看这种最基础的权限都拎不清。这套系统的核心参与者是三类管理员、教师、学生。在实际的课程考试场景里管理员负责系统配置和基础数据维护专业、班级、课程教师负责题库和试卷的创建与管理学生则是纯粹的考生角色。为了简化实现很多毕业设计会把管理员和教师合并成一个管理端角色只保留学生作为独立端这类取舍在源码中很常见也完全合理。从业务闭环来看一条完整的考试链路是这样的教师登录管理端 → 添加/导入题目到题库 → 选择题目手动或自动组卷 → 设置考试时间、时长、参与班级 → 发布考试 → 学生在规定时间内登录考生端 → 在线答题 → 提交试卷 → 系统自动判分客观题 → 教师人工评阅主观题 → 学生查看成绩 → 教师查看成绩统计与分析这个闭环里任何一个环节断裂系统体验都会大打折扣。比如自动判分只处理了选择题简答题却没有任何阅卷入口或者考试发布后学生端看不到考试入口又或者交卷后成绩迟迟不出现——这些都是在设计阶段就需要提前堵上的逻辑缺口。2. 数据库设计考试系统最核心的地基2.1 核心表结构与设计思路这套系统的数据库拆开来看其实就六张核心表外加两张辅助表。把这八张表的关系理清并落地为MySQL DDL是整个项目最关键的一步。我按实际业务流转顺序来说明。用户表sys_user存储所有人的账号信息。关键字段是role字段用1、2、3区分管理员、教师、学生。这里有个设计细节值得注意——密码字段我强烈建议存MD5或BCrypt加密后的密文而不是明文。很多毕设源码直接明文存密码一旦数据库泄露就是大事故这个习惯从学项目阶段就要养成。题库表question这是考试的内容源也是最需要认真设计的表。核心字段包括题目类型1单选、2多选、3判断、4简答、所属课程ID、题目内容、选项A/B/C/D用四个字符串字段或者JSON存储、正确答案、分值、难度等级。题目类型字段会直接影响后端的判分逻辑所以设计时要留好扩展空间——比如以后要加填空题类型枚举值往前追加即可。试卷表exam_paper记录一次考试用到的试卷。这里有两种设计流派一种是把题目ID以逗号分隔的字符串存到一个字段里简单但查询麻烦另一种是建一张试卷-题目关联表规范但表多一张。多数可直接运行的源码采用的是第一种冗余设计因为对于这种量级的系统性能差异几乎感知不到反而代码实现更简洁。考试表exam描述一次具体的考试任务。关键字段所属试卷ID、考试名称、开始时间、结束时间、考试时长、总分、及格分、参与班级范围、考试状态未开始/进行中/已结束。注意考试时间和考试时长是两个概念——时长用于考生端倒计时开始/结束时间用于控制考试入口的开放和关闭。答题记录表exam_record记录某考生某次考试的整体情况。核心字段考生ID、考试ID、试卷ID、得分、交卷时间、答题状态考试中/已交卷/待阅卷/已完成。这张表是整个系统的账本成绩统计全部要JOIN到它。答题明细表answer_detail记录考生对每一道题的具体作答。核心字段答题记录ID、题目ID、考生答案纯文本或JSON、是否得分、得分值。客观题可以在交卷瞬间自动判分并写入得分主观题先置为待阅卷由教师后续在后台进行人工评分。2.2 表关系与索引设计经验表之间的关系我用一句话总结exam_record是连接考生与考试的中枢answer_detail是判分的操作台。具体来说sys_user 和 exam_record一对多一个考生可以参加多次考试exam 和 exam_record一对多一次考试有多名考生参与exam_record 和 answer_detail一对多一条答题记录对应多道题的作答明细exam_paper 和 question多对多通过题目的ID列表或关联表实现索引方面除了主键索引外至少要对以下字段建立索引exam_record 表的 (student_id, exam_id) 联合索引——这是查询频率最高的场景要快速定位某个考生在某场考试中的答题情况exam_record 表的 exam_id 单列索引——用于成绩统计时按考试维度聚合question 表的 course_id 和 question_type——出题和组卷时最常用的过滤维度建索引的代价是多占一点磁盘空间但在数据量上来之后查询性能的差距是数量级的。当年我调过一个线上问题成绩列表查询要5秒加了联合索引后降到50毫秒以内这种优化几乎是白捡的性能。关于建表时的engine和字符集有一个关键点表引擎使用InnoDB支持事务字符集使用utf8mb4兼容表情符号和更多生僻字排序规则使用utf8mb4_general_ci即可。开发阶段这些细节容易忽略但等部署到生产环境再改字符集那才叫真正的折腾。3. 后端核心功能实现要点3.1 SpringBoot项目的工程结构与接口划分这套系统的后端工程结构规整的写法是标准的Maven分层结构com.example.exam ├── controller // 控制器层接收前端请求 ├── service // 业务逻辑层核心处理 ├── mapper // MyBatis或MyBatis-Plus数据访问层 ├── entity // 实体类 ├── dto // 数据传输对象 ├── config // 配置类跨域、拦截器、MyBatis-Plus配置 ├── common // 工具类、统一返回结构、异常处理 └── ExamApplication.java // 启动类在Controller的划分上我建议按照业务模块分而不是按角色分。也就是QuestionController题库接口、ExamController考试接口、ExamRecordController答题与成绩接口、AuthController登录认证、UserController用户管理。按角色分会导致一个Controller里混杂多种业务代码很快就乱成一锅粥。每个Controller返回统一的数据结构这是前后端协作顺畅的基石。我习惯用一个Result对象public class ResultT { private Integer code; // 200成功500失败 private String message; // 提示信息 private T data; // 数据载荷 }统一返回结构的好处是前端可以用一套拦截器处理所有响应不需要每个接口单独判断数据格式抽公共逻辑的成本就低很多。这套结构几乎已经是Java后端项目的通用规范了直接沿用就好。3.2 登录认证与权限控制考试系统有一个天然的安全诉求学生不能访问管理端接口教师不能篡改成绩。所以登录认证和权限控制是后端必须优先实现的基础设施。实现方案上常见的是JWT SpringBoot拦截器。具体流程是用户登录成功后后端验证账号密码生成一个JWT Token包含用户ID、角色等声明返回给前端前端把Token存放在localStorage中每次请求在请求头携带Authorization: Bearer token后端配置一个拦截器拦截所有需要登录的接口解析并验证Token的有效性在需要角色控制的接口上使用自定义注解或者简单地在业务逻辑里判断角色阻止越权访问JWT的好处是无状态服务器不需要保存session水平扩展时不需要做会话同步这对分布式部署很友好。毕业设计场景用它来讲解认证与授权的概念也特别合适。对于角色权限控制我在实际项目中是这么处理的定义角色常量在需要限制管理权限的Controller方法上加一个简单判断。数据库里面再为管理端建一个独立的菜单权限或按钮权限配置实现更细粒度的控制——不过对于考试系统这个业务场景角色级别的粗粒度控制已经够用没必要引入Spring Security这类重框架除非你对它非常熟并能控制好它的复杂性。3.3 题目管理与组卷逻辑题库管理是管理端使用频率最高的功能后端要实现的核心接口包括分页查询题目列表支持按类型、课程、难度筛选新增题目、编辑题目、删除题目批量导入题目可选用Excel解析组卷是考试系统里最体现业务理解的部分。手动组卷的逻辑是从题库中勾选题目设置每道题的分值加入试卷。自动组卷的逻辑则稍微复杂设定试卷总分如100分、各题型数量单选20题、多选10题、判断10题、简答4题、知识点范围系统从题库随机抽取符合条件且未被锁定的题目组成试卷。自动组卷的核心SQL写法基于MyBatis-Plus可以用简单的Wrapper实现ListQuestion questions questionMapper.selectList( new LambdaQueryWrapperQuestion() .eq(Question::getQuestionType, 1) // 单选 .eq(Question::getCourseId, courseId) // 课程范围 .eq(Question::getDifficulty, 2) // 难度 .last(ORDER BY RAND() LIMIT 20) // 随机取20道 );这里有个容易踩的坑如果题库数据量特别大——比如超过10万道题——直接ORDER BY RAND()会让数据库做全表扫描然后随机排序性能会很差。但考试系统的正常题库量级几千到几万道基本感知不到这个性能差异所以毕业设计和一般项目用这个写法完全没问题。想优化的话可以用先取ID在随机偏移量附近的数据这种策略但对这套系统来说属于过度设计。3.4 考试发布与自动判分逻辑考试发布接口的业务流程是前端提交考试信息试卷ID、考试名称、时间范围、时长、目标班级后端做两件事创建exam记录如果选了立即发布就把考试状态置为进行中。真正体现后端核心价值的是自动判分逻辑。判分时机我推荐在考生交卷时同步完成——判断所有客观题然后更新成绩、状态一把梭。这样做的好处是考生交卷那一刻就能看到成绩或者客观题部分成绩体验非常加分。判分逻辑核心代码大概是这个思路// 循环处理每道题的答案明细 for (AnswerDetail detail : answerDetails) { Question q questionMapper.selectById(detail.getQuestionId()); switch (q.getQuestionType()) { case 1: // 单选 case 3: // 判断 if (q.getCorrectAnswer().equals(detail.getStudentAnswer())) { detail.setScore(q.getScore()); totalScore q.getScore(); } break; case 2: // 多选答案比对需要转数组 String[] correctArr q.getCorrectAnswer().split(,); String[] studentArr detail.getStudentAnswer().split(,); Arrays.sort(correctArr); Arrays.sort(studentArr); if (Arrays.equals(correctArr, studentArr)) { detail.setScore(q.getScore()); totalScore q.getScore(); } break; case 4: // 简答跳过待人工阅卷 detail.setScore(0); break; } answerDetailMapper.updateById(detail); } // 更新考试记录总成绩 examRecord.setScore(totalScore); if (hasSubjectiveQuestions) { examRecord.setStatus(待阅卷); } else { examRecord.setStatus(已完成); } examRecordMapper.updateById(examRecord);多选的判分有个设计细节完全匹配才得分是保守策略一步到位不产生歧义如果想让多选部分匹配得分判断逻辑就需要改成正确项未选且选了错误项就不得分漏选按比例给分这种业务规则适合在后续迭代中加入初版用全匹配最稳。3.5 成绩统计与导出考试结束后的成绩统计是管理端的另一个高频模块。需要实现的维度包括单场考试的平均分、最高分、最低分、及格率、分数段分布按班级维度的横向对比每个学生的历史成绩趋势统计SQL的大致思路是// 平均分、及格率一次查询 SELECT COUNT(*) AS totalCount, AVG(score) AS avgScore, SUM(CASE WHEN score passScore THEN 1 ELSE 0 END) AS passCount FROM exam_record WHERE exam_id #{examId}这里有个业务反馈点很重要考试成绩的展示不同角色应该看到不同的数据。学生只能看到自己的成绩教师能看到全班甚至全年级的汇总管理员能看到整个系统的运行数据。这个数据隔离的需求在后端查询时要用意明确的WHERE条件控制好。导出功能如果需要做建议后端用EasyExcel或POI导出为Excel前端只需要触发一个下载接口就行。这个功能看着不起眼但在实际教学场景里频率非常高——老师学期末需要把成绩表存档或者上交教务处。4. Vue前端实现与交互细节4.1 前端工程结构与路由设计前端这块直接用Vue CLI或Vite创建工程配合Vue Router做路由控制UI组件库选Element UIVue 2时代最经典的组合或Element Plus如果用的是Vue 3。目录结构方面我的个人习惯是这样src ├── api // 封装axios请求 │ ├── user.js // 登录、用户相关的接口 │ ├── question.js // 题库相关接口 │ └── exam.js // 考试相关接口 ├── views // 页面组件 │ ├── admin // 管理端页面 │ │ ├── Dashboard.vue │ │ ├── QuestionManage.vue │ │ ├── ExamManage.vue │ │ └── ScoreAnalysis.vue │ └── student // 学生端页面 │ ├── ExamList.vue │ ├── ExamRoom.vue │ └── MyScore.vue ├── router // 路由配置 ├── store // 状态管理Vuex/Pinia ├── utils // 工具函数 └── App.vue路由设计上有个关键点要区分公共路由和权限路由。公共路由只包含登录页。登录成功后根据用户角色动态注入不同的路由表。管理端和考生端做成两套布局用路由嵌套的方式区分这样前端结构清晰也能避免考生误闯管理页面的尴尬。4.2 考生在线答题页的核心交互考生端的答题页是整个前端系统中最值得打磨的页面。它的核心诉求是让考生专注答题减少无关干扰同时提供足够的信息反馈。我推荐的布局是左侧答题区 右侧概览卡片结构。左侧按题目序号逐题展示题目内容、选项单选用radio、多选用checkbox、判断用radio、简答用textarea。右侧固定一个答题卡组件显示所有题号已经作答的显示高亮状态点击题号可以快速跳转到对应题目。倒计时是考试页的关键功能。实现上要注意几点倒计时数据在页面加载时从后端获取考试剩余秒数而不是直接用本地时间计算用setInterval每秒刷新显示当剩余时间小于5分钟时颜色变红提醒时间归零会自动触发交卷逻辑不能只在前端限制——后端在接收交卷请求时也要校验考试时间是否截止这里说一个我自己踩过的坑如果直接在前端用new Date()来计算倒计时考生改一下电脑系统时间倒计时就失效了。正确的做法是前后端都基于服务器时间登录后从接口拿服务器偏移量。反而是基于接口返回的截止时间戳来做本地倒计时用户根本没心思去改系统时间来作弊用不着过度设计防作弊。4.3 管理端页面的关键实现细节管理端页面相对常规但有两个模块的实现值得多说几句。题库管理页本质上就是一个表格 弹窗表单的组合。表格展示题目列表提供搜索筛选新增/编辑时弹窗显示表单根据题目类型动态显示不同的表单项——选单选判断要显示正确答案下拉框选多选要显示正确答案多选框选简答就不显示答案填写区或者只显示参考答案供人工阅卷参考。这个根据题目类型动态切换表单项的逻辑可以用Vue的计算属性加v-if简单实现el-form-item label正确答案 v-ifform.questionType 1 el-radio-group v-modelform.correctAnswer el-radio labelAA/el-radio el-radio labelBB/el-radio el-radio labelCC/el-radio el-radio labelDD/el-radio /el-radio-group /el-form-item el-form-item label正确答案 v-else-ifform.questionType 2 el-checkbox-group v-modelform.correctAnswer el-checkbox labelAA/el-checkbox ... /el-checkbox-group /el-form-item试卷配置页要支持手动/自动两种组卷方式。手动组卷用当前试卷题列表加左侧题库搜索的双栏布局勾选题目后移到右侧。这个交互我建议用两个表格中间加一个添加和移除按钮来实现逻辑直观且不容易出bug。自动组卷则是一堆表单项各题型数量、总分设置、抽取范围由后端完成随机抽题后返回结果前端把生成的试卷题目加载到表格里供预览和微调。4.4 Axios封装与前端鉴权所有前端请求都建议走统一的axios实例封装核心功能包括请求拦截器自动附加Token请求头响应拦截器统一解析Result对象如果code为401或Token过期跳转登录页全局错误提示请求失败时用Element UI的Message统一弹出错误信息Token过期处理尤其值得重视。考试系统里如果考生答题答到一半Token过期被迫退出登录这种体验基本就是灾难。所以考生端的答题提交通常建议做一次接口幂等性处理只要考生提交过答案后端就以已交卷为准重复提交时返回当前交卷状态而不是报错说未登录或登录过期。这种做法能极大提升容错性。5. 环境配置、打包部署与项目运行5.1 本地环境准备要跑起这套系统本地需要准备的环境如下我用一张表格整理好组件推荐版本说明JDK1.8 或 11SpringBoot 2.7.x 对JDK8支持最好Maven3.6后端依赖管理与打包Node.js14 / 16Vue CLI或Vite运行环境MySQL5.7 或 8.0数据库实例Navicat / MySQL Workbench任意图形化数据库管理工具IDEA / VS Code任意前后端IDE开发环境的搭建过程并不复杂但有个高发问题值得提前警告JDK、Maven、Node版本之间的兼容性。比如SpringBoot 2.7对应JDK8没问题但如果你硬配合JDK17部分自动配置的反射逻辑会报错Vue 2的工程在Node 17以上版本构建时经常会遇到OpenSSL相关的报错错误信息是ERR_OSSL_EVP_UNSUPPORTED解决办法是环境变量设置NODE_OPTIONS--openssl-legacy-provider或者直接使用Node 16版本。5.2 数据库初始化与后端配置数据库这步是整个部署里最需要细心的环节。先把源码附带的exam.sql脚本导入MySQL。导入后需要核对的关键配置项在application.yml中server: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/exam_system?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/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-plus: configuration: map-underscore-to-camel-case: true log-impl: org.apache.ibatis.logging.stdout.StdOutImpl这里我有三个血泪经验分享serverTimezoneAsia/Shanghai必须写。不然数据库连接时区不一致查出来的日期时间会差8个小时。MySQL 8.0和5.7的驱动类名不一样。MySQL 8要用com.mysql.cj.jdbc.Driver5.7用com.mysql.jdbc.Driver。不用看了直接用8的写法即可新环境基本都是8.0。密码千万别写在配置文件里提交到公开仓库。正确做法是生产环境用环境变量注入password: ${DB_PASSWORD}。5.3 前后端联调与跨域处理后端启动后执行mvn spring-boot:run或运行主类前端在开发环境默认访问http://localhost:8080后端端口这时候必然遇到跨域问题。解决跨域先在开发环境处理推荐用SpringBoot的全局CORS配置Configuration public class CorsConfig implements WebMvcConfigurer { Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(/**) .allowedOriginPatterns(*) .allowedMethods(GET, POST, PUT, DELETE, OPTIONS) .allowedHeaders(*) .allowCredentials(true) .maxAge(3600); } }注意一个细节如果前端请求开启了withCredentials携带Cookie后端allowedOrigins不能直接用*要指定具体的域名或用allowedOriginPatterns。这个坑排查起来很费时间建议一次到位。生产环境部署时更规范的做法是用Nginx做反向代理把前端静态资源和后端API合到同一域名下这样就不用处理跨域了server { listen 80; server_name exam.example.com; location / { root /usr/share/nginx/html; index index.html; try_files $uri $uri/ /index.html; # Vue Router history模式必须 } location /api/ { proxy_pass http://localhost:8080/; # 反向代理到后端 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }这个配置里有几个关键点第一条location前端页面刷新时不走后端路由导致404的问题就靠try_files解决第二条location前端所有API请求通过/api前缀代理到后端8080端口后端接口不需要再做跨域配置生产环境更安全。5.4 前端构建产物与部署Vue前端构建npm install npm run build构建完成后dist目录下就是纯静态文件直接扔给Nginx作为root目录即可。如果后端也想一起打包方便演示可以把dist复制到SpringBoot的src/main/resources/static目录下之后直接访问http://localhost:8080就能进入系统不再需要单独启动前端服务。这套前后端一体化部署方式在毕业设计演示时特别实用不用开两个服务一个Jar搞定。6. 常见问题与排障实录6.1 启动即报错的典型问题我根据经验把这套系统里的高发问题做了个速查表方便遇到时直接定位现象可能原因解决方案后端启动时报Failed to configure a DataSource数据库连接配置错误或MySQL未启动检查application.yml的url/用户名/密码前端启动后页面空白路由模式与服务器配置不匹配确认使用hash模式或Nginx配try_files登录接口返回401Token解析失败或登录接口路径不一致检查前端请求路径和后端RequestMapping是否一致无法连接到数据库3306端口被占用或防火墙拦截检查端口占用情况放行3306端口中文乱码MySQL字符集不匹配建库时指定utf8mb4连接串加characterEncodingutf8图片或附件上传失败静态资源路径或上传目录权限问题检查上传目录是否存在且可写或配置虚拟路径映射启动就挂的问题九成是数据库连接和字符集配置的问题先把这两项核查清楚再往下追。6.2 考试过程中的线上问题我实际遇到过两个特别值得展开的问题都跟考试业务直接相关。第一个是并发提交导致的成绩丢失。当时场景是全班50个学生同时交卷结果有几份卷子的成绩没有被正确写入。排查后发现原因是后端交卷接口的数据库操作没有加事务在并发请求下部分答题明细写入成功了但成绩汇总失败导致记录状态缺失。解决方案是在交卷Service方法上加Transactional注解确保整个判分和成绩更新过程要么全部成功、要么全部回滚。这个问题的教训是凡是涉及多张表更新的操作必须显式开启事务。第二个是考试状态刷新不及时。考试发布后学生端登录看不到考试入口怀疑是后端缓存问题。后来发现是前端查询考试列表时带了固定的status参数过滤后端没有把未开始状态当成可展示状态返回。调整思路是考试列表接口统一返回所有状态前端根据当前时间动态判断考试是否可进入、倒计时还是未开始。这样的好处是状态流转逻辑统一归前端处理后端只负责提供数据。6.3 让我少走弯路的三条经验最后分享三条在这个项目上沉淀下来的经验谈不上高深但确实能省不少时间。第一数据库表结构变更一定做好版本管理。开发过程中频繁改表结构每次改完都要同步更新建表脚本。拖到最后再统一导出SQL很容易漏字段漏修改。建议前期就建一个固定的sql/目录每次改动写一条ALTER语句进去保持脚本可追溯。第二前端接口联调一定要做异常分支的UI处理。考试系统的接口除了正常返回还有大量超时、Token失效、数据为空、权限不足的异常情况。前端每个请求最少把loading、成功、失败三态都考虑到。见过太多项目只处理了成功态一旦接口异常页面就白屏或卡死。第三始终从业务可用性的角度去衡量性能优化。选择题库查询加不加缓存、试卷加载用不用异步这些优化决策的前提是先搞清楚系统实际承载的并发量。作为一个考试系统高峰期就是一场大型考试的那一两个小时把接口该优化的地方优化好比如数据库索引、连接池大小剩下的时间根本不需要全链路缓存毕竟可观测性和维护难度才是长线成本。在线考试系统这类项目做好业务闭环和可运行两个维度价值就已经立住了。业务闭环保证每个角色用完都能解决真实问题可运行保证系统能被顺利部署、演示和二次开发。如果你正打算用这套源码做项目或学习参考建议先按第二条的部署流程完整跑起来感受一下整个链路再从数据库表设计入手精读代码你会发现很多设计细节的取舍逻辑都很值得琢磨。
返回列表