JAVA智能CAI平台考试系统源码 JAVA智能CAI平台考试系统源码本源码亲测可用!代码完整。 若有问题不能成功搭建包退!您自己搭建的过程中遇见技术问题可以免费咨询。 系统介绍:1、角色(1)管理员:网站管理员(全站管理)(2)教师:任课教师(发布课程,讨论)(后台添加)(3)学生:普通学生2、大致设计需求(1)学生(姓名、学校、专业、邮箱) 可以查看选课的成绩(2)老师发布课程(视频,文字说明,图片)供学生选课(3)学生选课,在线考试,讨论区(学生发加好友不要回复管理员看不到)。 (4)在线考试模块:考试 单选(直接出成绩)(5)选课 发短信(6)教学情况大数据统计:浏览课程根据页面显示,快速了解课程信息课程名称、讲师、课程简介、更新状态、学习人数、加好友数量、课程状态课程名称、课程简介、更新状态,学习人数搜索课程根据用户要求,快速查找课程学科分类、垂直领域难易度、热门课程、预告、已开课、有助教学科、职位、难易度、课程、最热课程、未学习课程选择课程根据用户需要,选择课程课程名称、讲师、课程简介、课程章节、常见问题、报名趋势、报名人数、开课时间、知识储备、相关分类课程名称、课程简介、课程大纲、教师简介、报名人数、课程时长、课程难度、课程须知、可以学到什么知识学习课程深入学习课程课件、课程信息、讨论区、wiki、课程进度、课程大纲、扩展学习资料 课程视频、课程列表。 关注课程、讨论区、笔记、wiki、同学列表、分享课程、课程下载\\r

先看学生选课这个核心场景。系统用JPA做了个带级联操作的实体映射,注意看Course和Student的关联设计:

@Entity
public class Student {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    // 选课关系配置
    @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    @JoinTable(name = "student_course",
        joinColumns = @JoinColumn(name = "student_id"),
        inverseJoinColumns = @JoinColumn(name = "course_id"))
    private Set<Course> selectedCourses = new HashSet<>();
    
    // 其他字段省略...
}

// 选课服务中的关键方法
@Transactional
public void selectCourse(Long studentId, Long courseId) {
    Student student = studentRepo.findById(studentId)
        .orElseThrow(() -> new BizException("学生不存在"));
    Course course = courseRepo.findById(courseId)
        .orElseThrow(() -> new BizException("课程不存在"));
    
    if(student.getSelectedCourses().add(course)) {
        smsService.sendEnrollSuccess(student.getPhone(), course.getName());
    }
}

这里用@ManyToMany维护选课关系,注意级联设置避免误删课程。事务注解保证选课和短信发送的原子性,遇到并发选课时Set结构能天然去重。

考试模块的设计更有意思,自动阅卷功能用策略模式实现:

// 评分策略接口
public interface ScoringStrategy {
    int calculateScore(ExamSubmission submission);
}

// 单选题策略实现
@Component
public class SingleChoiceScoring implements ScoringStrategy {
    @Override
    public int calculateScore(ExamSubmission submission) {
        return submission.getAnswers().entrySet().stream()
            .mapToInt(entry -> {
                Question q = questionRepo.findById(entry.getKey())
                    .orElseThrow();
                return q.getCorrectOption().equals(entry.getValue()) 
                    ? q.getScore() : 0;
            }).sum();
    }
}

// 考试提交服务
@Service
@RequiredArgsConstructor
public class ExamService {
    private final Map<String, ScoringStrategy> strategies;
    
    public void submitExam(ExamSubmission submission) {
        ScoringStrategy strategy = strategies.get(submission.getExamType()+"Scoring");
        int score = strategy.calculateScore(submission);
        submission.setAutoScore(score);
        examRecordRepo.save(submission);
        
        // 实时更新学生总成绩
        studentRepo.updateTotalScore(submission.getStudentId(), score);
    }
}

通过Spring的自动类型注入,不同题型可以有独立的计分策略。这种设计让新增题型评分策略时不需要修改主流程代码,符合开闭原则。

讨论区的敏感词过滤采用了DFA算法优化:

public class SensitiveFilter {
    private static class TrieNode {
        private final Map<Character, TrieNode> children = new HashMap<>();
        private boolean isEnd;
    }

    private final TrieNode root = new TrieNode();

    // 初始化构建字典树
    public void init(Set<String> sensitiveWords) {
        sensitiveWords.forEach(word -> {
            TrieNode node = root;
            for (char c : word.toCharArray()) {
                node = node.children.computeIfAbsent(c, k -> new TrieNode());
            }
            node.isEnd = true;
        });
    }

    // 过滤处理
    public String filter(String content) {
        char[] chars = content.toCharArray();
        StringBuilder result = new StringBuilder();
        for(int i=0; i<chars.length; ) {
            TrieNode node = root;
            int matchLength = 0;
            for(int j=i; j<chars.length; j++) {
                node = node.children.get(chars[j]);
                if(node == null) break;
                if(node.isEnd) {
                    matchLength = j - i + 1;
                }
            }
            if(matchLength > 0) {
                result.append("***");
                i += matchLength;
            } else {
                result.append(chars[i++]);
            }
        }
        return result.toString();
    }
}

这种实现相比正则匹配,时间复杂度从O(n^2)降到O(n),特别适合处理论坛高频发帖场景。注意初始化方法需要预热加载词库,实际项目中可以结合Redis做热更新。

JAVA智能CAI平台考试系统源码 JAVA智能CAI平台考试系统源码本源码亲测可用!代码完整。 若有问题不能成功搭建包退!您自己搭建的过程中遇见技术问题可以免费咨询。 系统介绍:1、角色(1)管理员:网站管理员(全站管理)(2)教师:任课教师(发布课程,讨论)(后台添加)(3)学生:普通学生2、大致设计需求(1)学生(姓名、学校、专业、邮箱) 可以查看选课的成绩(2)老师发布课程(视频,文字说明,图片)供学生选课(3)学生选课,在线考试,讨论区(学生发加好友不要回复管理员看不到)。 (4)在线考试模块:考试 单选(直接出成绩)(5)选课 发短信(6)教学情况大数据统计:浏览课程根据页面显示,快速了解课程信息课程名称、讲师、课程简介、更新状态、学习人数、加好友数量、课程状态课程名称、课程简介、更新状态,学习人数搜索课程根据用户要求,快速查找课程学科分类、垂直领域难易度、热门课程、预告、已开课、有助教学科、职位、难易度、课程、最热课程、未学习课程选择课程根据用户需要,选择课程课程名称、讲师、课程简介、课程章节、常见问题、报名趋势、报名人数、开课时间、知识储备、相关分类课程名称、课程简介、课程大纲、教师简介、报名人数、课程时长、课程难度、课程须知、可以学到什么知识学习课程深入学习课程课件、课程信息、讨论区、wiki、课程进度、课程大纲、扩展学习资料 课程视频、课程列表。 关注课程、讨论区、笔记、wiki、同学列表、分享课程、课程下载\\r

统计模块的难点在于动态条件查询,用MyBatis的动态SQL实现挺合适:

<select id="selectCourseStats" resultType="CourseStatDTO">
    SELECT 
        c.name,
        COUNT(sc.student_id) AS enrollCount,
        AVG(e.score) AS avgScore
    FROM course c
    LEFT JOIN student_course sc ON c.id = sc.course_id
    LEFT JOIN exam_record e ON c.id = e.course_id
    <where>
        <if test="params.difficulty != null">
            AND c.difficulty = #{params.difficulty}
        </if>
        <if test="params.startDate != null">
            AND c.create_time >= #{params.startDate}
        </if>
        <if test="params.teacherId != null">
            AND c.teacher_id = #{params.teacherId}
        </if>
    </where>
    GROUP BY c.id
    ORDER BY enrollCount DESC
    LIMIT 100
</select>

这种动态拼接SQL的方式在简单统计场景下,比用JPA的Criteria API更直观。不过要注意连表查询的性能,当数据量过大时需要分库分表或上OLAP方案。

整个系统最妙的是状态机的运用,比如课程生命周期管理:

public enum CourseState {
    DRAFT, PUBLISHED, STARTED, ENDED, ARCHIVED;
    
    private static final Map<CourseState, Set<CourseState>> transitions = Map.of(
        DRAFT, Set.of(PUBLISHED),
        PUBLISHED, Set.of(STARTED, DRAFT),
        STARTED, Set.of(ENDED),
        ENDED, Set.of(ARCHIVED),
        ARCHIVED, Collections.emptySet()
    );
    
    public void checkTransition(CourseState newState) {
        if (!transitions.get(this).contains(newState)) {
            throw new StateTransitionException("非法状态转换");
        }
    }
}

// 在课程修改服务中
public void changeCourseState(Long courseId, CourseState newState) {
    Course course = courseRepo.findById(courseId)
        .orElseThrow();
    course.getCurrentState().checkTransition(newState);
    course.setCurrentState(newState);
    courseRepo.save(course);
    
    if(newState == PUBLISHED) {
        notifySubscribers(course); // 通知预约学生
    }
}

用枚举实现状态模式,明确限定状态流转路径,比用if-else堆砌更清晰。这在涉及业务流程控制的系统中特别重要,能有效避免脏数据产生。

这套代码最值得借鉴的是业务抽象能力——把选课、考试、讨论这些教学场景转化为可扩展的技术实现。特别是策略模式和状态模式的应用,让后续新增考试类型或课程状态时改动范围最小化。不过实际部署时要注意,短信服务和敏感词过滤这些模块需要做降级处理,防止第三方服务不可用影响主流程。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐