1. 项目背景与核心需求
在线考试系统在高校信息化建设中扮演着越来越重要的角色。传统纸质考试存在组织成本高、阅卷效率低、成绩统计慢等问题,而基于Spring Boot的在线考试平台能够有效解决这些痛点。我去年为某职业技术学院开发的这套系统,上线后帮助教务部门减少了约70%的考试组织工作量。
这个系统的核心需求可以归纳为三个维度:
- 考生端:需要支持多种题型(选择/填空/简答)的在线作答、倒计时提醒、自动保存答案等功能
- 教师端:要求具备题库管理、试卷生成、在线监考、智能阅卷等教学管理能力
- 管理端:需要实现用户权限管理、考试数据分析、系统监控等后台功能
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术架构设计
2.1 整体技术栈选型
经过技术评估,我们采用以下技术组合:
- 后端框架:Spring Boot 2.7 + Spring Security
- 持久层:MyBatis-Plus 3.5 + PageHelper
- 数据库:MySQL 8.0(主从架构)
- 缓存:Redis 6.2(试题缓存+会话管理)
- 实时通信:WebSocket(用于考试倒计时推送)
- 前端:Vue 3 + Element Plus
提示:Spring Boot版本选择2.7.x而非3.0+,主要考虑企业环境对JDK17的适配尚不普及
2.2 微服务化设计考量
虽然单体架构也能满足基础需求,但考虑到后期可能扩展在线培训功能,我们采用模块化设计:
code复制exam-system
├── exam-auth // 认证中心
├── exam-gateway // API网关
├── exam-question // 题库服务
├── exam-paper // 试卷服务
└── exam-judge // 阅卷服务
这种设计带来两个关键优势:
- 可以按需部署,小型考试只需启动核心模块
- 各服务可独立扩展,比如阅卷服务在期末时可临时扩容
3. 核心功能实现细节
3.1 高并发考试入场设计
考试开始前15分钟通常是访问高峰,我们通过三级缓存解决:
- 本地缓存:使用Caffeine缓存基础考场信息
- Redis缓存:存储考生座位安排等动态数据
- 数据库分片:按考场ID哈希分片
关键代码示例:
java复制@Cacheable(value = "examRoom", key = "#roomId")
public ExamRoom getExamRoom(String roomId) {
// 先查Redis
String redisKey = "exam:room:" + roomId;
ExamRoom room = redisTemplate.opsForValue().get(redisKey);
if(room == null) {
// 查数据库
room = examRoomMapper.selectById(roomId);
redisTemplate.opsForValue().set(redisKey, room, 30, TimeUnit.MINUTES);
}
return room;
}
3.2 实时保存答题记录
为防止网络中断导致答案丢失,我们设计双保险机制:
- 前端自动保存:每30秒自动提交一次答案
- WebSocket保活:建立长连接监测考生在线状态
数据库表设计特别注意了version字段:
sql复制CREATE TABLE `exam_answer` (
`id` bigint NOT NULL AUTO_INCREMENT,
`exam_id` bigint NOT NULL,
`question_id` bigint NOT NULL,
`student_answer` text,
`version` int DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `idx_exam_question` (`exam_id`,`question_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
4. 安全防护方案
4.1 防作弊措施
我们实现了三重防护:
- 界面锁定:全屏考试模式下无法切换窗口
- 行为监测:鼠标离开考试页面超过3次触发警告
- 人脸识别:通过OpenCV实现活体检测
4.2 数据安全策略
所有敏感数据都进行加密处理:
- 传输层:HTTPS + 自定义报文加密
- 存储层:AES加密考生答案
- 日志:敏感字段自动脱敏
关键配置示例:
yaml复制security:
encryption:
key: ${ENCRYPT_KEY:defaultKey123}
enabled: true
ssl:
enabled: true
keystore: classpath:keystore.p12
5. 部署与性能优化
5.1 容器化部署方案
采用Docker Compose编排服务:
yaml复制version: '3'
services:
mysql-master:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PWD}
ports:
- "3306:3306"
redis:
image: redis:6.2-alpine
ports:
- "6379:6379"
5.2 JVM调优经验
通过GC日志分析发现,阅卷服务频繁发生Young GC。最终调整参数:
code复制-XX:+UseG1GC
-XX:MaxGCPauseMillis=200
-XX:InitiatingHeapOccupancyPercent=45
-Xms2g -Xmx2g
调整后GC时间从平均300ms降至80ms,这在批量阅卷时效果尤为明显。
6. 踩坑与解决方案
6.1 MyBatis分页插件冲突
同时使用PageHelper和MyBatis-Plus的分页功能时,会出现拦截器执行顺序问题。解决方案:
- 排除MyBatis-Plus自带分页
- 统一使用PageHelper配置
java复制@Configuration
public class MyBatisConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 注意不添加分页插件
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}
}
6.2 WebSocket会话管理
初期设计没有考虑Nginx反向代理的情况,导致WebSocket连接频繁断开。需要添加配置:
nginx复制location /ws {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 3600s;
}
7. 扩展功能展望
在实际使用中,我们发现可以进一步优化:
- 智能组卷算法:根据知识点分布自动生成试卷
- 语音监考:结合WebRTC实现远程语音监控
- 考试数据分析:使用ELK栈分析考生答题模式
这套系统经过两个学期的实际运行,成功支持了累计5万+人次的在线考试。最大的收获是认识到:在线考试不是简单地把纸质考试电子化,而是需要重新设计整个考试流程。比如我们增加的"考试前设备自检"功能,就显著减少了开考时的技术支持请求。
