AIGrader:一个 AI 作业批改平台的 Java EE 课设实战

AIGrader:一个 AI 作业批改平台的 Java EE 课设实战

教师布置作业,AI 秒级批改,学生即时查看并订正,教师复核确认------一个完整的作业批改闭环。


目录


这个项目是什么

AIGrader 是一个基于 AI 的中小学作业批改平台。教师在线布置作业,学生在线答题,AI 自动批改并生成评语,学生查看结果后可以订正,教师最终复核确认。

核心闭环:教师布置 → AI 秒级批改 → 学生查看与订正 → 教师复核

技术栈

层级 技术
后端框架 Spring Boot 3.4.5 + Java 21 + Maven
AI 引擎 Spring AI 1.0.0-M6 + DeepSeek(支持动态切换模型)
安全认证 Spring Security + JWT(无状态 Token)
数据库 PostgreSQL 16 + pgvector 扩展
缓存 Redis 7(DB=2)
前端框架 React 18 + Vite + TypeScript
UI 组件 Ant Design 5
图表 Recharts 2.15
状态管理 Zustand

项目地址:github.com/xiaodangjia105/AIGrader

这是我的 Java EE 课程设计项目,一个人完成的全栈开发。后端 63 个 Java 文件,前端 21 个 TS/TSX 文件,9 张数据库表,30+ 个 REST API。


功能全景

系统有三种角色:教师、学生、管理员。每个角色看到的界面和能做的事完全不同。

教师端

功能 说明
作业管理 创建作业、从题库选题组卷、查看布置历史
AI 批改结果查看 查看每个学生的 AI 批改结果,含分数、评语、扣分原因
批改复核 对 AI 批改结果进行人工修正,调整分数或评语
个性化评语 AI 根据学生历史表现生成个性化评语,教师可编辑后发送
班级统计 查看班级完成率、平均分、分数分布

学生端

功能 说明
查看作业 查看教师布置的待完成作业列表
在线答题 支持选择题、判断题、填空题、简答题、作文题
查看批改结果 即时查看 AI 批改的分数、评语和正确答案
错题订正 对错误答案进行订正,系统记录订正历史
学习报告 AI 分析薄弱知识点,生成个性化学习建议

管理后台

功能 说明
题库管理 题目的 CRUD 操作,支持 JSON/CSV 批量导入
用户管理 查看和管理所有用户
AI 配置 动态切换 AI 模型和 API Key,无需重启服务
AI 准确率趋势 跟踪 AI 批改的准确率变化

技术架构

#mermaid-svg-i3p4rRFrXi48UwZR{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-i3p4rRFrXi48UwZR .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-i3p4rRFrXi48UwZR .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-i3p4rRFrXi48UwZR .error-icon{fill:#552222;}#mermaid-svg-i3p4rRFrXi48UwZR .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-i3p4rRFrXi48UwZR .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-i3p4rRFrXi48UwZR .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-i3p4rRFrXi48UwZR .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-i3p4rRFrXi48UwZR .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-i3p4rRFrXi48UwZR .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-i3p4rRFrXi48UwZR .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-i3p4rRFrXi48UwZR .marker{fill:#333333;stroke:#333333;}#mermaid-svg-i3p4rRFrXi48UwZR .marker.cross{stroke:#333333;}#mermaid-svg-i3p4rRFrXi48UwZR svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-i3p4rRFrXi48UwZR p{margin:0;}#mermaid-svg-i3p4rRFrXi48UwZR .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-i3p4rRFrXi48UwZR .cluster-label text{fill:#333;}#mermaid-svg-i3p4rRFrXi48UwZR .cluster-label span{color:#333;}#mermaid-svg-i3p4rRFrXi48UwZR .cluster-label span p{background-color:transparent;}#mermaid-svg-i3p4rRFrXi48UwZR .label text,#mermaid-svg-i3p4rRFrXi48UwZR span{fill:#333;color:#333;}#mermaid-svg-i3p4rRFrXi48UwZR .node rect,#mermaid-svg-i3p4rRFrXi48UwZR .node circle,#mermaid-svg-i3p4rRFrXi48UwZR .node ellipse,#mermaid-svg-i3p4rRFrXi48UwZR .node polygon,#mermaid-svg-i3p4rRFrXi48UwZR .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-i3p4rRFrXi48UwZR .rough-node .label text,#mermaid-svg-i3p4rRFrXi48UwZR .node .label text,#mermaid-svg-i3p4rRFrXi48UwZR .image-shape .label,#mermaid-svg-i3p4rRFrXi48UwZR .icon-shape .label{text-anchor:middle;}#mermaid-svg-i3p4rRFrXi48UwZR .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-i3p4rRFrXi48UwZR .rough-node .label,#mermaid-svg-i3p4rRFrXi48UwZR .node .label,#mermaid-svg-i3p4rRFrXi48UwZR .image-shape .label,#mermaid-svg-i3p4rRFrXi48UwZR .icon-shape .label{text-align:center;}#mermaid-svg-i3p4rRFrXi48UwZR .node.clickable{cursor:pointer;}#mermaid-svg-i3p4rRFrXi48UwZR .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-i3p4rRFrXi48UwZR .arrowheadPath{fill:#333333;}#mermaid-svg-i3p4rRFrXi48UwZR .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-i3p4rRFrXi48UwZR .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-i3p4rRFrXi48UwZR .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-i3p4rRFrXi48UwZR .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-i3p4rRFrXi48UwZR .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-i3p4rRFrXi48UwZR .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-i3p4rRFrXi48UwZR .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-i3p4rRFrXi48UwZR .cluster text{fill:#333;}#mermaid-svg-i3p4rRFrXi48UwZR .cluster span{color:#333;}#mermaid-svg-i3p4rRFrXi48UwZR div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-i3p4rRFrXi48UwZR .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-i3p4rRFrXi48UwZR rect.text{fill:none;stroke-width:0;}#mermaid-svg-i3p4rRFrXi48UwZR .icon-shape,#mermaid-svg-i3p4rRFrXi48UwZR .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-i3p4rRFrXi48UwZR .icon-shape p,#mermaid-svg-i3p4rRFrXi48UwZR .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-i3p4rRFrXi48UwZR .icon-shape .label rect,#mermaid-svg-i3p4rRFrXi48UwZR .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-i3p4rRFrXi48UwZR .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-i3p4rRFrXi48UwZR .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-i3p4rRFrXi48UwZR :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 后端
前端
React + TypeScript
Axios + JWT 拦截器
Spring Security + JWT
Controller 层
Service 层
AI 批改引擎
Repository 层
PostgreSQL + pgvector
Redis 7
Spring AI + DeepSeek

后端采用标准的 Spring Boot 分层架构:

  • Controller 层(8 个控制器):处理 HTTP 请求,参数校验,调用 Service
  • Service 层(10 个服务):核心业务逻辑,事务管理
  • Repository 层(9 个仓库):JPA 数据访问,自动建表
  • Entity 层(9 个实体):数据库表映射
  • DTO 层(12 个对象):数据传输对象,隔离内部模型和 API 契约

前端结构:

  • Pages:按角色分组------教师端 5 页、学生端 5 页、管理后台 4 页
  • Components:共享组件(表格、表单、图表)
  • Services:API 调用层,Axios + JWT 拦截器
  • Store:Zustand 状态管理

数据库有 9 张表,其中 PostgreSQL 的 pgvector 扩展用于存储和检索向量数据(支持未来的智能题目推荐功能)。Redis 用于 JWT Token 黑名单和会话缓存。


核心模块:AI 批改引擎

这是整个系统最核心的部分。不同题型的批改逻辑完全不同------选择题可以精确匹配,填空题需要模糊匹配,主观题需要 AI 理解语义。用一个统一的接口处理所有题型,是策略模式的典型应用场景。

策略模式设计

java 复制代码
public interface GradingStrategy {
    /**
     * 批改一道题
     * @param question 题目信息(题干、正确答案、分值)
     * @param answer 学生答案
     * @return 批改结果(分数、评语、扣分原因)
     */
    GradingResult grade(Question question, String answer);
}

三个实现类:

  • ChoiceGradingStrategy(选择题/判断题):精确匹配答案,不需要调 AI。分数要么满分要么零分。
  • FillBlankGradingStrategy(填空题):先精确匹配,失败后调 AI 做语义相似度判断。比如答案是"二氧化碳",学生写了"CO2",也算对。
  • SubjectiveGradingStrategy(简答题/作文题):调 DeepSeek API,让 AI 根据评分标准打分。

工厂模式根据题型分发:

java 复制代码
public class GradingStrategyFactory {
    private final Map<QuestionType, GradingStrategy> strategies;

    public GradingStrategy getStrategy(QuestionType type) {
        GradingStrategy strategy = strategies.get(type);
        if (strategy == null) {
            throw new IllegalArgumentException("不支持的题型: " + type);
        }
        return strategy;
    }
}

Prompt 工程

主观题批改的关键在 Prompt 设计。PromptTemplateService 按学科组织 Prompt 模板,不同学科的评分标准不同:

  • 数学:看计算过程是否正确、步骤是否完整、最终答案是否准确
  • 语文:看表达是否通顺、逻辑是否清晰、是否有错别字
  • 英语:看语法是否正确、词汇是否恰当、表达是否地道

AI 要求返回结构化的 JSON:

json 复制代码
{
  "score": 85,
  "maxScore": 100,
  "comment": "解题思路正确,但第三步计算有误",
  "deductions": [
    {"reason": "第三步符号错误", "points": 10},
    {"reason": "缺少单位", "points": 5}
  ]
}

结构化输出的好处:前端可以直接渲染每个扣分项,学生能清楚看到哪里扣了分、为什么扣。

降级策略

AI 调用可能失败(网络超时、API 限流)。系统做了降级处理:AI 不可用时,主观题给默认分数并标记"待人工复核",不会阻断整个批改流程。


核心模块:个性化评语与学习报告

个性化评语(CommentService)

传统做法:教师手动写评语,工作量大,而且很难做到个性化。

AIGrader 的做法:AI 根据学生的答题历史和成绩趋势自动生成评语。Prompt 里包含学生最近 5 次作业的成绩、本次作业的得分、错误题目类型等上下文,让 AI 生成有针对性的评语。

比如一个学生上次考了 60 分,这次考了 85 分,AI 会生成"进步明显,尤其是应用题部分有了很大提升,继续保持"。如果一个学生连续三次在几何题上丢分,AI 会建议"几何部分需要加强,建议复习三角形全等的判定条件"。

教师可以编辑 AI 生成的评语后再发送给学生。

学习报告(ReportService)

学习报告是学生端的核心功能。ReportService 分析学生的所有答题记录,生成:

  • 薄弱知识点分析:按题目标签统计正确率,找出正确率最低的知识点
  • 成绩趋势:最近 N 次作业的分数变化曲线
  • AI 学习建议:根据薄弱知识点,推荐具体的复习方向

报告数据用 Recharts 在前端渲染成图表,学生一目了然。


核心模块:动态模型切换

AiConfigService 实现了一个不需要重启服务就能切换 AI 模型的能力。

配置存储在数据库的 ai_config 表中,包含:

  • 当前使用的模型名称(如 deepseek-chat
  • API Key
  • API Base URL
  • 模型参数(temperature、max_tokens 等)

管理后台的"AI 配置"页面可以修改这些配置,保存后立即生效。下次 AI 调用时,AiConfigService 从数据库读取最新配置,用 Spring AI 的统一接口创建新的客户端实例。

这个设计的好处:

  • 不重启切换模型:DeepSeek 不稳定时,可以切到通义千问或 Kimi
  • API Key 轮换:Key 过期或泄露时,直接在界面上换
  • 参数调优:调整 temperature 来控制 AI 评分的稳定性

Spring AI 的价值在这里体现得很明显------它提供了统一的 AI 调用接口,切换底层模型只需要改配置,代码不需要动。


核心模块:认证与权限

JWT 无状态认证

系统使用 Spring Security + JWT 实现无状态认证。用户登录后签发 Token,后续请求通过 Token 认证,服务端不存储会话状态。

三种角色的权限隔离:

角色 能访问的 API
教师 /api/assignments/**/api/grading/**/api/statistics/**
学生 /api/submissions/**/api/student/**
管理员 /api/admin/**/api/questions/**

@PreAuthorize 注解在 Controller 方法上声明权限:

java 复制代码
@PreAuthorize("hasRole('TEACHER')")
@PostMapping("/assignments")
public ResponseEntity<ApiResponse<Assignment>> createAssignment(...) { ... }

Token 黑名单

JWT 签发后到过期前无法单方面废止。系统用 Redis 实现了 Token 黑名单:用户登出时,把 Token 的唯一标识加入 Redis,设置过期时间等于 Token 剩余有效期。验证 Token 时先查黑名单,命中则拒绝。


前端实现

技术选型

前端用 React 18 + TypeScript + Vite 构建,UI 组件库选 Ant Design 5。状态管理用 Zustand------比 Redux 轻量得多,一个文件就能定义一个 store,不需要 action、reducer、middleware 那一套。

页面结构

复制代码
frontend/src/pages/
├── LoginPage.tsx          # 登录页(共用)
├── teacher/
│   ├── AssignmentPage.tsx # 作业管理
│   ├── GradingPage.tsx    # 批改结果查看
│   ├── ReviewPage.tsx     # 批改复核
│   ├── StatisticsPage.tsx # 班级统计
│   └── CommentPage.tsx    # 个性化评语
├── student/
│   ├── HomeworkPage.tsx   # 作业列表
│   ├── AnswerPage.tsx     # 在线答题
│   ├── ResultPage.tsx     # 批改结果
│   ├── CorrectPage.tsx    # 错题订正
│   └── ReportPage.tsx     # 学习报告
└── admin/
    ├── QuestionPage.tsx   # 题库管理
    ├── UserPage.tsx       # 用户管理
    ├── AiConfigPage.tsx   # AI 配置
n    └── AccuracyPage.tsx   # AI 准确率趋势

API 调用层

Axios 实例配置了 JWT 拦截器:

  • 请求拦截:自动从 Zustand store 读取 Token,附加到请求头
  • 响应拦截:遇到 401 自动跳转登录页,清除本地 Token

所有 API 调用统一封装在 services/api.ts 中,按模块分组(auth、assignment、submission、grading 等)。

图表

Recharts 用于两个核心场景:

  • 班级统计:柱状图展示分数分布,折线图展示平均分趋势
  • 学习报告:雷达图展示各知识点掌握程度,折线图展示成绩变化

总结与收获

这个课设让我从零搭建了一个完整的全栈应用,覆盖了后端开发、前端开发、AI 集成、数据库设计、安全认证等多个方面。

几个关键收获:

策略模式的实际应用。AI 批改引擎用策略模式处理不同题型,比 if-else 链清晰得多,新增题型只需要加一个实现类。

Prompt 工程的重要性。AI 批改的质量取决于 Prompt 的设计。结构化输出(JSON)让前端可以直接渲染,不需要再做文本解析。

Spring AI 的价值。统一的 AI 调用接口让模型切换变得很简单------改配置就能切模型,代码不需要动。

无状态认证的取舍。JWT 让后端可以水平扩展,但 Token 无法主动失效,需要额外引入 Redis 黑名单。没有银弹,只有 trade-off。

当前的局限:只支持单 Sheet 的作业模板、AI 调用有延迟(批量批改时较慢)、大数据量下性能有待优化。后续计划支持多 Sheet、批量转换和本地模型。

项目地址:github.com/xiaodangjia105/AIGrader

觉得有用的话,点个 Star 支持一下。

相关推荐
weikecms1 小时前
消费返物业费 + 小区本地生活 CPS 系统|微客云(物业 / 社区 / 本地服务商首选)
人工智能·微信·微客云
用户9940573931451 小时前
从 Workflow 到 Agent:读 Anthropic 与 OpenAI Agent 指南后的理解
人工智能
萤丰信息1 小时前
存量焕新 + 绿色低碳,2026 智慧园区转型新路径
大数据·人工智能
ZPC82101 小时前
如何将机械臂末端定位精度提升至微米如何进行标定
人工智能·算法·机器人
黑暗森林观察者1 小时前
DiffusionGemma:扩散模型从"画图"走向"写文章",文本生成速度提升4倍
人工智能
Web极客码1 小时前
使用人工智能翻译WordPress网站
服务器·人工智能·wordpress
m沐沐1 小时前
【深度学习】PyTorch CNN 手写数字识别(卷积神经网络)
人工智能·pytorch·python·深度学习·机器学习·pycharm·cnn
字节跳动数据库1 小时前
AI 失控处理术
人工智能·claude
devilnumber1 小时前
Lambda|行为参数化 完整精讲
java·lambda·行为参数化