在线考试系统的设计与实现
一、需求分析与技术选型
1. 核心需求梳理
系统需实现以下核心功能:
- 多角色管理:学生(参加考试、查询成绩)、教师(创建题库、组卷、阅卷)、管理员(用户管理、系统设置)
- 题库管理:支持单选题、多选题、判断题和简答题,可批量导入试题
- 在线考试:定时交卷、防作弊(禁止切屏)、异常断线后可续考
- 自动阅卷:客观题自动评分,主观题教师手动评分
- 成绩统计:按班级、科目统计平均分、及格率等数据
2. 技术选型考量
- 后端:Spring Boot 2.7.x(开发效率高,适合快速迭代)
- 前端:Bootstrap 5 + jQuery(响应式设计,适配电脑和手机)
- 数据库:MySQL 8.0(关系型数据库,适合存储结构化考试数据)
- 开发工具:IntelliJ IDEA + AI 辅助编码插件
二、环境准备
1. 下载并安装 IntelliJ IDEA
选择社区版进行安装。注意勾选添加到环境变量及创建桌面快捷方式。
2. 配置开发环境
安装 JDK 8+,配置 Maven,初始化 MySQL 数据库。
三、模块设计与编码
在 AI 辅助下,按'需求描述→拆解分析→设计→编码'的流程系统化开发。以下是核心代码示例:
1. 实体类设计
Question.java(试题实体)
package com.student.exam.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("question")
public class Question {
@TableId(type = IdType.AUTO)
private Long id;
private String content;
private Integer type;
private String optionA;
private String optionB;
private String optionC;
private String optionD;
private String correctAnswer;
private Integer score;
private Integer difficulty;
private String subject;
private Long createBy;
private LocalDateTime createTime;
private Integer status;
}
ExamRecord.java(考试记录实体)
package com.student.exam.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("exam_record")
public class ExamRecord {
@TableId(type = IdType.AUTO)
private Long id;
private Long studentId;
private Long paperId;
private Integer status;
private LocalDateTime startTime;
private LocalDateTime endTime;
private BigDecimal score;
private Integer totalScore;
private Integer screenChangeCount;
private LocalDateTime lastOperateTime;
}
2. 数据传输对象(DTO)
PaperCreateDTO.java(试卷创建请求 DTO)
package com.student.exam.dto;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Positive;
import lombok.Data;
import java.util.List;
@Data
public class PaperCreateDTO {
@NotBlank(message = "试卷名称不能为空")
private String paperName;
@NotBlank(message = "学科不能为空")
private String subject;
@NotNull(message = "考试时长不能为空")
@Positive(message = "考试时长必须大于 0")
private Integer examDuration;
@NotNull(message = "试卷总分不能为空")
@Positive(message = "试卷总分必须大于 0")
private Integer totalScore;
private List<Long> questionIds;
@Data
public static class RandomPaperParam {
@NotBlank(message = "随机组卷需指定学科")
private String subject;
@NotNull(message = "随机组卷需指定单选题数")
@Positive(message = "单选题数必须大于 0")
private Integer singleCount;
}
}
3. 业务逻辑实现
ExamServiceImpl.java(考试服务实现类)
package com.student.exam.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.student.exam.dto.ExamSubmitDTO;
import com.student.exam.entity.*;
import com.student.exam.enums.ExamStatusEnum;
import com.student.exam.mapper.*;
import com.student.exam.service.ExamService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.stream.Collectors;
@Slf4j
@Service
@RequiredArgsConstructor
public class ExamServiceImpl extends ServiceImpl<ExamRecordMapper, ExamRecord> implements ExamService {
private final ExamRecordMapper examRecordMapper;
private final PaperMapper paperMapper;
private final QuestionMapper questionMapper;
private final AnswerSheetMapper answerSheetMapper;
private final UserMapper userMapper;
@Override
@Transactional
public void submitExam {
log.info(, submitDTO.getExamRecordId(), submitDTO.getStudentId());
examRecordMapper.selectById(submitDTO.getExamRecordId());
(examRecord == || !ExamStatusEnum.IN_PROGRESS.equals(examRecord.getStatus())) {
();
}
BigDecimal.ZERO;
( answer : submitDTO.getAnswers()) {
questionMapper.selectById(answer.getQuestionId());
question.getCorrectAnswer().equals(answer.getStudentAnswer());
totalScore = totalScore.add(BigDecimal.valueOf(isCorrect ? question.getScore() : ));
}
examRecord.setStatus(ExamStatusEnum.SUBMITTED);
examRecord.setScore(totalScore);
examRecordMapper.updateById(examRecord);
}
String {
(answer == || answer.isEmpty()) ;
java.util.Arrays.stream(answer.split()).sorted().collect(Collectors.joining());
}
}
四、网页展示
1. 学生端 - 考试列表页
采用 Bootstrap 卡片式布局,显示试卷名称、学科、状态等信息。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>我的考试</title>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container mt-4">
<h4>我的考试</h4>
<div class="row">
<div class="col-md-6 col-lg-4">
<div class="card exam-card available">
<h5>Java 编程基础期末测试</h5>
<p>学科:Java 编程 | 时长:90 分钟 | 总分:100 分</p>
<button class="btn btn-primary">开始考试</button>
</>
2. 学生端 - 考试答题页
包含倒计时、切屏检测、自动保存等功能。
<div class="exam-header d-flex justify-content-between">
<h5>剩余时间:<span id="remainingTime">01:25:30</span></h5>
<span>切屏次数:<span id="screenChangeCount">3</span></span>
</div>
<div class="question-item">
<p>下列关于 Java 中'继承'的描述,正确的是?</p>
<label><input type="radio" name="q1"> A. Java 支持多继承</label>
<label><input type="radio" name="q1"> B. 子类可以重写父类的方法</label>
</div>
3. 教师端 - 试题管理页
支持试题增删改查、批量导入及筛选。
<table class="table table-hover">
<thead>
<tr><th>ID</th><th>题干</th><th>题型</th><th>操作</th></tr>
</thead>
<tbody>
<tr><td>1</td><td>下列关于 Java 中'继承'的描述...</td><td>单选题</td><td><button>编辑</button></td></tr>
</tbody>
</table>
五、开发总结与展望
1. 开发收获
- 技术能力提升:掌握 Spring Boot + MyBatis-Plus 开发流程,学会 Bootstrap 响应式布局。
- 解决问题能力:面对 Excel 批量导入失败、考试计时偏差等问题,通过查阅文档和调试定位根源。
- 项目管理意识:将复杂项目分解为模块,按优先级逐步实现。
2. 系统不足与优化方向
- 防作弊功能可完善:添加摄像头监控、禁止复制粘贴。
- 智能组卷算法:根据知识点分布自动生成试卷。
- 大数据分析:对学生答题数据进行分析,找出易错知识点。
3. 建议
- 善用开发工具:AI 辅助生成基础代码,但核心逻辑需自己思考。
- 重视代码规范:写注释、用有意义的变量名、遵循设计模式。
本次开发从 0 到 1 构建了一个实用的在线考试系统,在实践中学习和成长。