1. 项目背景与核心需求
在线教育行业近年来呈现爆发式增长,特别是在后疫情时代,各类教学机构对数字化考试系统的需求激增。传统纸质考试存在组织成本高、阅卷效率低、防作弊难度大等问题,而市面上的通用考试系统往往无法满足特定学科(如编程、设计等)的在线训练需求。
这个学生在线训练课程考试系统主要解决三个核心痛点:
- 支持编程题、设计题等特殊题型的在线作答与自动评判
- 实现训练过程中的实时反馈与错题分析
- 提供完善的防作弊机制与考试过程监控
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术选型与架构设计
2.1 前端技术栈选择
采用Vue.js作为前端框架主要基于以下考量:
- 组件化开发模式适合构建复杂的考试界面(如题目区、答题区、监控区并行显示)
- 响应式特性可适配不同终端设备(PC/平板)
- 丰富的生态插件(如代码编辑器、公式渲染等)
关键插件选型:
- Monaco Editor:用于在线代码编辑与高亮
- MathJax:数学公式渲染
- WebRTC:实现人脸识别与屏幕监控
2.2 后端技术栈选择
Spring Boot框架的优势体现在:
- 快速构建RESTful API满足前后端分离需求
- 内置安全机制(Spring Security)处理认证授权
- 丰富的starter简化集成(如Redis、RabbitMQ等)
系统采用分层架构设计:
code复制表现层:Vue + Element UI
业务层:Spring Boot + Spring Security
数据层:MySQL + Redis
文件存储:MinIO(支持大文件分片上传)
消息队列:RabbitMQ(异步处理判题任务)
3. 核心功能实现细节
3.1 在线考试模块
题目展示组件
vue复制<template>
<div class="question-container">
<div v-if="question.type === 'code'">
<monaco-editor
v-model="answer.code"
:language="question.language"
:options="{ readOnly: isReviewMode }"
/>
</div>
<div v-else-if="question.type === 'math'">
<div v-html="renderMath(question.content)"></div>
<latex-editor v-model="answer.latex"/>
</div>
</div>
</template>
<script>
import { MathJax } from 'mathjax-full/es5/tex-svg';
export default {
methods: {
renderMath(content) {
return MathJax.tex2svg(content).innerHTML;
}
}
}
</script>
考试状态管理
使用Vuex实现全局状态管理:
javascript复制const store = new Vuex.Store({
state: {
exam: {
remainingTime: 0,
questions: [],
currentIndex: 0
}
},
mutations: {
nextQuestion(state) {
if(state.exam.currentIndex < state.exam.questions.length-1) {
state.exam.currentIndex++;
}
},
// 自动保存答案到本地存储
saveAnswer(state, payload) {
localStorage.setItem(`answer_${payload.qid}`, payload.answer);
}
}
})
3.2 自动判题系统
判题服务设计
java复制@Service
public class JudgeService {
@Autowired
private RabbitTemplate rabbitTemplate;
// 提交判题任务
public void submitJudgeTask(JudgeTask task) {
rabbitTemplate.convertAndSend(
"judge.exchange",
"judge.routingKey",
task
);
}
// 处理判题结果
@RabbitListener(queues = "result.queue")
public void handleJudgeResult(JudgeResult result) {
// 更新数据库
answerRepository.updateResult(
result.getAnswerId(),
result.getStatus(),
result.getScore()
);
// 实时推送前端
simpMessagingTemplate.convertAndSend(
"/topic/result/" + result.getUserId(),
result
);
}
}
代码题判题流程
- 用户提交代码
- 系统生成Docker容器
- 执行测试用例
- 检查运行结果
- 静态代码分析(可选)
- 返回评分与反馈
3.3 防作弊机制实现
多维度监控方案
| 监控类型 | 实现方式 | 技术要点 |
|---|---|---|
| 人脸识别 | WebRTC + TensorFlow.js | 每分钟抓取并比对基准照片 |
| 屏幕监控 | rrweb录制 | 全操作过程录制回放 |
| 切屏检测 | Page Visibility API | 记录切屏次数与时长 |
| 代码查重 | SimHash算法 | 比对代码相似度 |
javascript复制// 切屏检测实现
document.addEventListener('visibilitychange', () => {
if(document.hidden) {
store.commit('recordTabSwitch', {
timestamp: Date.now(),
duration: 0 // 通过轮询计算实际时长
});
}
});
4. 性能优化实践
4.1 前端优化方案
- 懒加载:按需加载题目资源
- 虚拟滚动:长列表性能优化
- 本地缓存:答案自动保存策略
- Web Worker:复杂计算任务分离
4.2 后端优化策略
- Redis缓存热点数据:
java复制@Cacheable(value = "questions", key = "#id")
public Question getQuestionById(Long id) {
return questionRepository.findById(id).orElseThrow();
}
- 数据库分库分表:
- 按课程ID水平分片
- 考试记录按月分表
- 判题服务集群化:
- 基于Docker Swarm的动态扩容
- 优先级队列管理(考试任务优先)
5. 部署方案与监控
5.1 容器化部署
dockerfile复制# 前端Dockerfile
FROM nginx:alpine
COPY dist/ /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
# 后端Dockerfile
FROM openjdk:11-jre
COPY target/exam-system.jar /app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
5.2 监控体系搭建
- Prometheus:采集JVM/系统指标
- Grafana:可视化监控面板
- ELK:日志收集与分析
- Sentry:前端错误追踪
6. 踩坑经验与解决方案
6.1 代码题判题超时问题
现象:复杂算法题执行超时导致判题失败
解决方案:
- 动态设置超时阈值(根据题目难度)
- 添加资源限制:
java复制docker run --rm -m 512m --cpus 1 ...
6.2 高并发提交时的消息堆积
优化方案:
- 分级队列策略(VIP用户优先处理)
- 消费者自动扩容机制
- 添加死信队列处理失败任务
6.3 前端内存泄漏
常见场景:
- WebRTC连接未关闭
- EventBus监听未移除
- 大对象缓存未清理
检测工具:
- Chrome Memory面板
- Vue DevTools性能分析
7. 扩展功能建议
-
智能组卷系统:
- 基于知识图谱的题目推荐
- 难度系数自动平衡算法
-
AI监考助手:
- 行为异常检测(如频繁低头)
- 声音环境分析(环境噪音监测)
-
学习路径推荐:
- 根据错题记录生成训练计划
- 相似考生对比分析
这个系统的开发过程中,最深刻的体会是:在线考试系统不是简单的题目展示+答案收集,而是需要构建完整的教学闭环。我们在第二版迭代中加入了"错题视频讲解"功能,当学生查看错题时,系统自动推送相关知识点微课,这个改进使课程完课率提升了35%。
