一、项目简介

本项目是一个面向学校和教育机构的在线作业管理平台,覆盖了作业发布 → 学生提交 → 教师批改 → 成绩统计的完整流程。

1🎯 核心亮点:本系统内置作业查重功能,教师可对某次作业的所有提交进行文本相似度检测,有效识别抄袭行为。查重结果以相似度分数呈现,帮助教师快速定位疑似抄袭的作业,维护学术诚信。

1.1 核心角色

角色 核心功能
学生 查看作业、提交作业(含文件上传)、查看成绩与反馈、修改个人资料(需审批)
教师 发布作业(按学生定向分配)、批改作业(评分+评语)、查看班级成绩统计、作业查重检测
管理员 用户管理(增删改查)、审核资料修改申请、全局数据查看

1.2 系统功能模块

  • 🔐 用户认证:注册/登录/忘记密码(验证码找回)/JWT 令牌 + Refresh Token
  • 📝 作业管理:创建、编辑、删除、按班级定向发布、截止时间控制、状态管理(published/expired/withdrawn)
  • 📤 作业提交:多格式文件上传(PDF/Word/ZIP/图片等)、截止时间控制、重新提交、附件删除
  • ✏️ 作业批改:评分(含满分校验)、评语、教师查看所有提交
  • 🔍 作业查重:文本相似度检测、抄袭识别、查重报告、按相似度排序
  • 📊 成绩统计:平均分/最高分/最低分、提交率/批改率、学生个人详情、ECharts 可视化图表
  • 🔔 消息通知:系统通知、作业提醒、成绩通知、永久消息/临时通知分类
  • 📋 申请审批:学生资料修改申请 → 管理员审核(通过/拒绝)
  • 📎 文件管理:附件上传、下载(含 Content-Type 自动识别)、文件大小校验

二、环境配置

在开始使用本项目前,请确保以下环境已安装并正确配置。

2.1 环境要求

软件 最低版本 推荐版本 说明
JDK 24.0.1+ 24.0.1 Java 开发工具包
Maven 3.9.14+ 3.9.14 后端构建工具
Node.js 24.14.1+ 24.14.1 前端运行时
npm 11.11.0+ 11.11.0 前端包管理
MySQL 5.7+ 8.0+ 关系数据库
Redis 6.0+ 7.0+ 缓存数据库

2.2 环境安装

JDK 24 安装

  1. 从 Oracle JDK 或 OpenJDK 下载 JDK 24
  2. 配置环境变量:JAVA_HOME = JDK 安装路径,PATH 中添加 %JAVA_HOME%\bin
  3. 验证:java -versionjavac -version

Maven 安装

  1. 从 Maven 官网 下载 3.9.14+
  2. 配置环境变量:MAVEN_HOME = 解压路径,PATH 中添加 %MAVEN_HOME%\bin
  3. 验证:mvn -version

Node.js 安装

  1. 从 Node.js 官网 下载 v24.14.1 LTS 版本
  2. 验证:node -vnpm -v
  3. 推荐配置国内镜像:npm config set registry https://registry.npmmirror.com

MySQL 安装

  1. 从 MySQL 官网 下载安装
  2. 记住 root 密码(本项目默认配置为 123456
  3. 确保 MySQL 服务已启动

Redis 安装(Windows)

方式一 — WSL2:

bash

wsl --install
sudo apt update && sudo apt install redis-server
sudo service redis-server start

方式二 — Memurai:Redis-Compatible, Enterprise-Grade In-Memory Caching for Windows | Memurai 下载安装开发版。


三、技术栈

3.1 后端

技术 版本 用途
Spring Boot 3.4.5 核心框架
Spring Security + JWT jjwt 0.12.6 认证与授权(无状态 JWT + RBAC)
Spring Data JPA ORM 持久层
MyBatis Plus 3.5.9 复杂查询增强
MySQL 5.7+ 关系数据库
Redis(Lettuce 连接池) 6.0+ 缓存与 Token 管理
Caffeine Cache 3.2.0 本地缓存(用户查询缓存)
SpringDoc OpenAPI 2.8.4 API 文档自动生成(Swagger UI)
Apache POI 5.4.0 Excel 导入导出
iText 7 9.1.0 PDF 生成
Lombok 1.18.38 简化代码
Maven 3.9.14+ 构建工具

3.2 前端

技术 版本 用途
Vue 3.5.13 核心框架(Composition API)
Pinia 3.0.1 状态管理(替代 Vuex)
Vue Router 4.5.0 路由管理(含路由懒加载)
Element Plus 2.9.7 UI 组件库
@element-plus/icons-vue 2.3.1 图标库
ECharts + vue-echarts 5.6.0 / 7.0.3 数据可视化
Axios 1.7.9 HTTP 请求
Vite 6.0.11 构建工具(开发服务器+代理)
dayjs 1.11.13 日期处理
NProgress 0.2.0 页面加载进度条
js-cookie 3.0.5 Cookie 管理
file-saver + xlsx 文件下载与 Excel 导出
Sass 1.83.4 CSS 预处理器
unplugin-auto-import 19.0.0 自动导入 Vue API
unplugin-vue-components 28.0.0 自动导入 Element Plus 组件

四、项目架构

4.1 目录结构

4.2 前后端交互流程

┌─────────────┐     HTTP/REST      ┌─────────────┐     JDBC/JPA     ┌──────────┐
│   Vue 3     │ ◄────────────────► │  Spring Boot │ ◄──────────────► │  MySQL   │
│  前端 :3000  │   Axios + Proxy   │  后端 :8080  │                  │  数据库   │
└─────────────┘                    └──────┬───────┘                  └──────────┘
                                         │
                                         │ Caffeine / Redis
                                         ▼
                                   ┌──────────┐
                                   │  缓存层   │
                                   └──────────┘
  • 5前端通过 Vite 开发服务器运行在 localhost:3000
  • 后端运行在 localhost:8080,context-path 为 /api
  • 跨域通过 Vite proxy 代理解决(开发环境),后端也配置了 CORS(生产环境)
  • 认证采用 JWT 无状态 Token,前端存入 Cookie,每次请求通过 Axios 拦截器自动注入 Authorization: Bearer <token>

五、数据库设计

系统包含 6 张核心表,完整建表语句见项目根目录的 online_homework_system_complete.sql

5.1 users — 用户表

sql

CREATE TABLE `users` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `username` varchar(255) NOT NULL COMMENT '用户名',
  `password` varchar(255) NOT NULL COMMENT '密码(BCrypt 加密)',
  `name` varchar(255) NOT NULL COMMENT '姓名',
  `role` varchar(50) NOT NULL COMMENT '角色(STUDENT/TEACHER/ADMIN)',
  `email` varchar(255) COMMENT '邮箱',
  `phone` varchar(50) COMMENT '手机号',
  `department` varchar(255) COMMENT '院系/部门',
  `major` varchar(255) COMMENT '专业',
  `student_id` varchar(50) COMMENT '学号',
  `avatar` mediumtext COMMENT '头像 URL 或 Base64',
  `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `updated_at` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_username` (`username`),
  KEY `idx_role` (`role`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

5.2 homework — 作业表

sql

CREATE TABLE `homework` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `title` varchar(255) NOT NULL COMMENT '作业标题',
  `description` text COMMENT '作业描述',
  `teacher_id` bigint NOT NULL COMMENT '教师 ID',
  `course_name` varchar(255) COMMENT '课程名称',
  `deadline` datetime COMMENT '截止时间',
  `max_score` double COMMENT '满分',
  `allow_modification` tinyint(1) DEFAULT 1 COMMENT '是否允许修改提交',
  `status` varchar(50) DEFAULT 'published' COMMENT '状态(published/expired/withdrawn)',
  `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `updated_at` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `idx_teacher_id` (`teacher_id`),
  KEY `idx_status` (`status`),
  KEY `idx_deadline` (`deadline`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

5.3 homework_student — 作业-学生关联表

sql

CREATE TABLE `homework_student` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `homework_id` bigint NOT NULL COMMENT '作业 ID',
  `student_id` bigint NOT NULL COMMENT '学生 ID',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_homework_student` (`homework_id`, `student_id`),
  KEY `idx_student_id` (`student_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

5.4 submissions — 提交表

sql

CREATE TABLE `submissions` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `homework_id` bigint NOT NULL COMMENT '作业 ID',
  `student_id` bigint NOT NULL COMMENT '学生 ID',
  `content` text COMMENT '作业内容',
  `file_path` varchar(500) COMMENT '文件路径',
  `submitted_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `score` double COMMENT '分数',
  `feedback` text COMMENT '评语',
  `graded_at` timestamp NULL COMMENT '批改时间',
  `status` varchar(50) DEFAULT 'submitted' COMMENT '状态(submitted/graded)',
  `similarity_score` double COMMENT '相似度分数',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_homework_student` (`homework_id`, `student_id`),
  CONSTRAINT `fk_submission_homework` FOREIGN KEY (`homework_id`) REFERENCES `homework` (`id`) ON DELETE CASCADE,
  CONSTRAINT `fk_submission_student` FOREIGN KEY (`student_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

5.5 message — 消息通知表

sql

CREATE TABLE `message` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `title` varchar(255) NOT NULL COMMENT '消息标题',
  `content` text COMMENT '消息内容',
  `sender_id` bigint COMMENT '发送者 ID',
  `receiver_id` bigint NOT NULL COMMENT '接收者 ID',
  `type` varchar(50) DEFAULT 'notification' COMMENT '类型(notification/permanent/system)',
  `status` varchar(50) DEFAULT 'active' COMMENT '状态(active/inactive)',
  `is_read` tinyint(1) DEFAULT 0 COMMENT '是否已读',
  `expire_time` datetime COMMENT '过期时间',
  `notification_id` varchar(255) COMMENT '通知 ID(用于批量操作)',
  `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  CONSTRAINT `fk_message_sender` FOREIGN KEY (`sender_id`) REFERENCES `users` (`id`) ON DELETE SET NULL,
  CONSTRAINT `fk_message_receiver` FOREIGN KEY (`receiver_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

5.6 profile_requests — 资料申请审批表

sql

CREATE TABLE `profile_requests` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `user_id` bigint NOT NULL COMMENT '用户 ID',
  `username` varchar(255) NOT NULL COMMENT '用户名',
  `name` varchar(255) NOT NULL COMMENT '姓名',
  `email` varchar(255) COMMENT '邮箱',
  `phone` varchar(50) COMMENT '手机号',
  `department` varchar(255) COMMENT '院系',
  `major` varchar(255) COMMENT '专业',
  `student_id` varchar(50) COMMENT '学号',
  `avatar` mediumtext COMMENT '头像',
  `status` varchar(50) NOT NULL DEFAULT 'pending' COMMENT '状态(pending/approved/rejected)',
  `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `updated_at` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `idx_user_id` (`user_id`),
  KEY `idx_status` (`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

5.7 ER 关系图(文字版)

users (1) ──────< homework_student >────── (N) homework
  │                                              │
  │ (teacher_id)                                 │
  └──────────────────────────────────────────────┘
  │
  ├── (1) ────< submissions >──── (N)
  │               │
  │               └──── (N:1) ──── homework
  │
  ├── (1) ────< message (sender) >──── (N)
  ├── (1) ────< message (receiver) >─── (N)
  │
  └── (1) ────< profile_requests >──── (N)

六、核心功能实现

6.1 JWT 认证 + RBAC 权限控制

使用 Spring Security + JWT 实现无状态认证:

java

// SecurityConfig.java — 核心安全配置
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfig {
    
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .csrf(AbstractHttpConfigurer::disable)
            .cors(cors -> cors.configurationSource(corsConfigurationSource()))
            .exceptionHandling(exception -> exception
                .authenticationEntryPoint(jwtAuthenticationEntryPoint))
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/auth/**", "/public/**").permitAll()
                .requestMatchers("/users/verification-code", "/users/verify-code",
                                 "/users/reset-password").permitAll()
                .requestMatchers("/admin/**").hasRole("ADMIN")
                .requestMatchers("/teacher/**").hasAnyRole("TEACHER", "ADMIN")
                .requestMatchers("/student/**")
                    .hasAnyRole("STUDENT", "TEACHER", "ADMIN")
                .requestMatchers("/v3/api-docs/**", "/swagger-ui/**",
                                 "/swagger-ui.html").permitAll()
                .anyRequest().authenticated()
            )
            .sessionManagement(session -> session
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS))
            .authenticationProvider(authenticationProvider())
            .addFilterBefore(jwtAuthenticationFilter,
                UsernamePasswordAuthenticationFilter.class);
        return http.build();
    }
}

RBAC 角色设计:基于 ROLE_ADMINROLE_TEACHERROLE_STUDENT 三种角色,通过 @PreAuthorize 注解实现方法级权限控制。

  • @PreAuthorize("hasAnyRole('TEACHER', 'ADMIN')") — 创建/编辑/删除作业
  • @PreAuthorize("hasRole('STUDENT')") — 提交作业
  • @PreAuthorize("hasRole('ADMIN')") — 用户管理、审批

6.2 缓存策略

项目同时使用了 Redis 和 Caffeine 本地缓存

  • Redis:配置在 application.yml 中,使用 Lettuce 连接池(max-active: 20 / max-idle: 10 / min-idle: 5),用于分布式场景下的数据共享
  • Caffeine 本地缓存:最大 500 条目,30 分钟未访问过期,命中率目标 > 80%

java

// RedisConfig.java — 实际配置的是 Caffeine 本地缓存
@Configuration
@EnableCaching
public class RedisConfig {
    
    @Bean
    public CacheManager cacheManager() {
        CaffeineCacheManager cacheManager = new CaffeineCacheManager();
        cacheManager.setCaffeine(Caffeine.newBuilder()
                .maximumSize(500)
                .expireAfterAccess(30, TimeUnit.MINUTES)
                .recordStats());
        return cacheManager;
    }
}

6.3 全局异常处理

统一的异常处理与返回格式:

java

@RestControllerAdvice
public class GlobalExceptionHandler {
    
    @ExceptionHandler(ResourceNotFoundException.class)
    public ResponseEntity<ApiResponse<?>> handleNotFound(ResourceNotFoundException ex) {
        return ResponseEntity.status(404)
            .body(ApiResponse.error(404, ex.getMessage()));
    }
    
    @ExceptionHandler(AccessDeniedException.class)
    public ResponseEntity<ApiResponse<?>> handleAccessDenied(AccessDeniedException ex) {
        return ResponseEntity.status(403)
            .body(ApiResponse.error(403, "权限不足"));
    }
    
    @ExceptionHandler(Exception.class)
    public ResponseEntity<ApiResponse<?>> handleGeneral(Exception ex) {
        return ResponseEntity.status(500)
            .body(ApiResponse.error(500, "服务器内部错误"));
    }
}

统一响应格式:

json

// 成功
{ "code": 200, "message": "操作成功", "data": { ... } }

// 失败
{ "code": 400, "message": "错误信息", "data": null }

6.4 前端 Axios 封装

统一的请求/响应拦截器,自动注入 Token,Token 过期自动跳转登录:

javascript

// utils/request.js
import axios from 'axios'
import { ElMessage } from 'element-plus'
import router from '@/router'

const request = axios.create({
  baseURL: '/api',
  timeout: 10000
})

// 请求拦截器 — 注入 JWT Token
request.interceptors.request.use(config => {
  const token = localStorage.getItem('token')
  if (token) {
    config.headers.Authorization = `Bearer ${token}`
  }
  return config
})

// 响应拦截器 — 统一错误处理
request.interceptors.response.use(
  response => response.data,
  error => {
    if (error.response?.status === 401) {
      localStorage.removeItem('token')
      router.push('/login')
    }
    ElMessage.error(error.response?.data?.message || '请求失败')
    return Promise.reject(error)
  }
)

export default request

6.5 前端路由权限守卫

javascript

// router/index.js
router.beforeEach((to, from, next) => {
  NProgress.start()

  const userStore = useUserStore()
  const token = userStore.token
  const userRole = userStore.role

  if (to.meta.requiresAuth && !token) {
    next({ name: 'Login', query: { redirect: to.fullPath } })
    NProgress.done()
  } else if (to.meta.requiresAuth && to.meta.roles &&
             !to.meta.roles.includes(userRole)) {
    ElMessage.error('您没有权限访问该页面')
    next({ name: 'Dashboard' })
    NProgress.done()
  } else {
    next()
  }
})

6.6 前端 Pinia 状态管理

使用 Pinia 管理用户登录状态,Token 和用户信息持久化到 Cookie(js-cookie):

javascript

// store/user.js
export const useUserStore = defineStore('user', () => {
  const token = ref(Cookies.get('token') || '')
  const user = ref(/* 从 Cookie 恢复 */)
  const role = ref(userInfo?.role || '')

  const loginAction = async (loginForm) => {
    const res = await login(loginForm)
    token.value = res.data.token
    user.value = { ...res.data, role: res.data.role?.toUpperCase() }
    Cookies.set('token', res.data.token)
    Cookies.set('userInfo', JSON.stringify(userData))
    return res
  }

  const logoutAction = async () => {
    token.value = ''
    user.value = null
    Cookies.remove('token')
    Cookies.remove('userInfo')
  }

  return { token, user, role, loginAction, logoutAction, ... }
})

6.7 作业查重功能 🔍

查重是本系统的一大亮点,旨在帮助教师快速识别学生作业中的抄袭行为。核心原理是基于文本相似度的两两比对算法,计算同一作业下不同学生提交内容的相似度分数。

6.7.1 实现原理

查重流程分为三个步骤:

第一步:提取所有提交内容

java

// SubmissionService.java — checkPlagiarism 方法
public List<Submission> checkPlagiarism(Long homeworkId) {
    // 1. 获取该作业的所有提交
    List<Submission> submissions = submissionRepository.findByHomeworkId(homeworkId);
    
    // 2. 为每个提交提取纯文本内容(去除HTML标签、标点符号等干扰)
    for (Submission sub : submissions) {
        String plainText = extractPlainText(sub.getContent());
        sub.setPlainText(plainText);
    }
    
    // 3. 两两比对计算相似度
    for (int i = 0; i < submissions.size(); i++) {
        for (int j = i + 1; j < submissions.size(); j++) {
            double similarity = calculateSimilarity(
                submissions.get(i).getPlainText(),
                submissions.get(j).getPlainText()
            );
            // 取该学生与其他所有学生比较的最高相似度
            submissions.get(i).setSimilarityScore(
                Math.max(submissions.get(i).getSimilarityScore(), similarity)
            );
            submissions.get(j).setSimilarityScore(
                Math.max(submissions.get(j).getSimilarityScore(), similarity)
            );
        }
    }
    
    // 4. 保存相似度结果到数据库
    submissionRepository.saveAll(submissions);
    
    // 5. 按相似度降序排列返回
    submissions.sort((a, b) -> 
        Double.compare(b.getSimilarityScore(), a.getSimilarityScore())
    );
    return submissions;
}

第二步:文本预处理

在计算相似度前,需要对提交内容进行清洗,去除无关信息:

java

private String extractPlainText(String content) {
    if (content == null) return "";
    // 去除 HTML 标签
    String text = content.replaceAll("<[^>]+>", "");
    // 去除标点符号和多余空白
    text = text.replaceAll("[\\p{P}\\p{S}]", "");
    // 统一转小写
    text = text.toLowerCase().trim();
    // 去除多余空格
    text = text.replaceAll("\\s+", " ");
    return text;
}

第三步:相似度计算

采用基于词频的余弦相似度算法,这是文本查重领域的经典方法:

java

private double calculateSimilarity(String text1, String text2) {
    if (text1.isEmpty() || text2.isEmpty()) return 0.0;
    
    // 分词
    String[] words1 = text1.split(" ");
    String[] words2 = text2.split(" ");
    
    // 构建词频向量
    Map<String, Integer> freq1 = buildWordFrequency(words1);
    Map<String, Integer> freq2 = buildWordFrequency(words2);
    
    // 获取所有不重复的词语
    Set<String> allWords = new HashSet<>();
    allWords.addAll(freq1.keySet());
    allWords.addAll(freq2.keySet());
    
    // 计算余弦相似度
    double dotProduct = 0.0;
    double norm1 = 0.0;
    double norm2 = 0.0;
    
    for (String word : allWords) {
        int count1 = freq1.getOrDefault(word, 0);
        int count2 = freq2.getOrDefault(word, 0);
        dotProduct += count1 * count2;
        norm1 += count1 * count1;
        norm2 += count2 * count2;
    }
    
    if (norm1 == 0 || norm2 == 0) return 0.0;
    return dotProduct / (Math.sqrt(norm1) * Math.sqrt(norm2));
}

private Map<String, Integer> buildWordFrequency(String[] words) {
    Map<String, Integer> freq = new HashMap<>();
    for (String word : words) {
        freq.merge(word, 1, Integer::sum);
    }
    return freq;
}
6.7.2 查重 API 接口

教师通过一个接口即可完成查重操作:

POST /api/submissions/homework/{homeworkId}/plagiarism
权限:TEACHER / ADMIN

返回结果按 similarityScore 降序排列,相似度越高的提交排在越前面,方便教师快速定位疑似抄袭的作业。

6.7.3查重结果呈现

查重完成后,每个提交记录的 similarity_score 字段会被更新,前端在批改列表中可以直观地看到每份作业的相似度分数。通常设定以下阈值:

相似度区间 判定结果 颜色标识
0% ~ 30% 正常 🟢 绿色
30% ~ 60% 可疑 🟡 黄色
60% ~ 100% 高度疑似抄袭 🔴 红色

💡 本系统的查重基于纯文本内容进行比对。如果作业涉及代码,建议结合专业代码查重工具(如 MOSS、JPlag)使用。

6.8 文件上传与下载

  • 上传:支持多格式文件(PDF/Word/ZIP/RAR/图片/文本),100MB 上限,自动校验文件类型和大小
  • 下载:自动识别文件 MIME 类型,正确设置 Content-Disposition 头,保留原始文件名和后缀
  • 存储:文件存储在 backend/uploads/submissions/ 目录下,以 时间戳_原始文件名 命名

七、API 接口一览(完整 40+ 接口)

7.1 认证模块 — 8 个接口

方法 路径 说明 权限
POST /api/auth/login 用户登录,返回 JWT + Refresh Token 匿名
POST /api/auth/register 用户注册 匿名
POST /api/auth/refresh 刷新令牌 匿名
POST /api/auth/logout 退出登录 认证
POST /api/auth/forgot-password/send-code 发送验证码(邮箱/手机) 匿名
POST /api/auth/forgot-password/verify-code 验证验证码 匿名
POST /api/auth/forgot-password/reset 重置密码 匿名
POST /api/auth/check-username 检查用户名是否存在 匿名
POST /api/auth/get-user-contacts 获取用户联系方式(脱敏) 匿名

7.2 用户模块 — 9 个接口

方法 路径 说明 权限
GET /api/users/me 获取当前用户信息 认证
GET /api/users/{id} 获取指定用户 认证
GET /api/users 获取所有用户(支持角色筛选) ADMIN
PUT /api/users/{id} 更新用户信息 认证
DELETE /api/users/{id} 删除用户 ADMIN
PUT /api/users/change-password 修改密码 认证
POST /api/users/verification-code 生成验证码 匿名
POST /api/users/verify-code 校验验证码 匿名
POST /api/users/reset-password 通过验证码重置密码 匿名

7.3 作业模块 — 12 个接口

方法 路径 说明 权限
POST /api/homework 创建作业(含学生分配) TEACHER/ADMIN
GET /api/homework/{id} 获取作业详情(含教师名) 认证
GET /api/homework/teacher/all 教师作业列表(支持课程/状态筛选) TEACHER/ADMIN
GET /api/homework/student/all 学生作业列表(含提交状态) STUDENT
GET /api/homework 获取所有作业 ADMIN
GET /api/homework/status/{status} 按状态查询作业 认证
PUT /api/homework/{id} 更新作业 TEACHER/ADMIN
DELETE /api/homework/{id} 删除作业 TEACHER/ADMIN
GET /api/homework/{id}/students 获取作业分配的学生 ID 列表 TEACHER/ADMIN
PUT /api/homework/{id}/students 更新作业分配的学生列表 TEACHER/ADMIN
GET /api/homework/teacher/with-submissions 获取有学生提交的作业 TEACHER/ADMIN
GET /api/homework/expired 获取过期作业 TEACHER/ADMIN

7.4 提交模块 — 12 个接口

方法 路径 说明 权限
POST /api/submissions 提交作业(含文件上传) STUDENT
GET /api/submissions/{id} 获取提交详情 认证
GET /api/submissions/student/all 获取学生的所有提交 STUDENT
GET /api/submissions/homework/{homeworkId} 获取作业的所有提交(含学生名) TEACHER/ADMIN
GET /api/submissions/homework/{homeworkId}/student 学生获取自己在某作业的提交 STUDENT
GET /api/submissions/teacher/all 教师查看所有提交 TEACHER/ADMIN
PUT /api/submissions/{id}/grade 批改作业(评分+评语) TEACHER/ADMIN
PUT /api/submissions/{id} 更新提交(含文件替换/删除) STUDENT
DELETE /api/submissions/{id} 删除提交 STUDENT
POST /api/submissions/homework/{homeworkId}/plagiarism 作业查重 TEACHER/ADMIN
GET /api/submissions/attachment/{id} 下载附件 认证
GET /api/submissions/homework/{homeworkId}/statistics 作业成绩统计 TEACHER/ADMIN

7.5 消息模块 — 5 个接口

方法 路径 说明 权限
GET /api/messages 获取消息列表 认证
GET /api/messages/{id} 获取消息详情 认证
GET /api/messages/unread 获取未读消息 认证
PUT /api/messages/{id}/read 标记为已读 认证
DELETE /api/messages/{id} 删除消息 认证

7.6 审批模块 — 7 个接口

方法 路径 说明 权限
POST /api/profile-requests 创建资料修改申请 认证
GET /api/profile-requests/my 获取自己的申请记录 认证
GET /api/profile-requests 获取所有申请 ADMIN
GET /api/profile-requests/pending 获取待审批申请 ADMIN
GET /api/profile-requests/{id} 获取申请详情 认证
PUT /api/profile-requests/{id}/approve 批准申请 ADMIN
PUT /api/profile-requests/{id}/reject 拒绝申请 ADMIN

完整的 40+ 个 API 接口可通过 Swagger 查看:
启动后端后访问 http://localhost:8080/api/swagger-ui.html


八、快速启动

💡 环境配置请参考 二、环境配置,确保 JDK、Maven、Node.js、MySQL、Redis 均已安装。

8.1 数据库初始化

bash

# 登录 MySQL
mysql -u root -p

# 创建数据库
CREATE DATABASE IF NOT EXISTS online_homework_system
DEFAULT CHARACTER SET utf8mb4
DEFAULT COLLATE utf8mb4_general_ci;

exit;

导入表结构和测试数据:

bash

# 推荐导入完整版(含测试账号和示例数据)
mysql -u root -p online_homework_system < online_homework_system_complete.sql

项目提供了两个 SQL 文件:

  • online_homework_system.sql — 仅表结构
  • online_homework_system_complete.sql — 表结构 + 测试数据(推荐)

导入后包含:4 个测试用户、3 个示例作业、2 条示例提交、3 条示例消息。

8.2 配置后端

修改 backend/src/main/resources/application.yml 中的数据库和 Redis 连接信息:

yaml

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/online_homework_system?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
    username: root           # 改为你的 MySQL 用户名
    password: 123456         # 改为你的 MySQL 密码
  data:
    redis:
      host: localhost        # Redis 地址
      port: 6379             # Redis 端口
      password:              # Redis 密码(如无则留空)

jwt:
  secret: your-default-jwt-secret-key-change-in-production
  expiration: 86400000       # Token 有效期(24小时,毫秒)
  refresh-expiration: 604800000  # Refresh Token 有效期(7天)

⚠️ 生产环境请务必修改 jwt.secret 为自定义密钥!

8.3 启动后端

bash

cd backend
mvn clean install -DskipTests
mvn spring-boot:run

或使用 IDE 启动:

  • IntelliJ IDEA:打开 backend 目录 → 找到 OnlineHomeworkSystemApplication.java → 右键 Run
  • VS Code:安装 Extension Pack for Java → 打开 backend → 按 F5 启动

验证:访问 http://localhost:8080/api/swagger-ui.html,看到 Swagger UI 页面即启动成功。

8.4 启动前端

bash

cd frontend
npm install
npm run dev

Vite 配置说明(vite.config.js 已配置好):

  • 开发服务器端口:3000
  • API 代理:/api → http://localhost:8080
  • 代码分割:Element Plus、Vue 生态、ECharts 独立打包
  • 自动导入:Element Plus 组件和 Vue API 按需自动导入

javascript

// vite.config.js 关键配置
server: {
  port: 3000,
  proxy: {
    '/api': {
      target: 'http://localhost:8080',
      changeOrigin: true,
    },
  },
},

启动后访问 http://localhost:3000

8.5 测试账号

角色 用户名 密码
管理员 admin admin123
教师 teacher1 teacher123
学生 student1 student123
学生 student2 student123

8.6 常见问题排查

Q1:后端启动报 "Access denied for user"

原因:MySQL 用户名或密码不正确。
解决:检查 application.yml 中 spring.datasource.username 和 password 配置。

Q2:后端启动报 "Unknown database"

原因:未创建数据库。
解决:执行 CREATE DATABASE online_homework_system DEFAULT CHARACTER SET utf8mb4;

Q3:Redis 连接失败

原因:Redis 服务未启动或配置错误。
解决:检查 Redis 服务是否运行,确认 application.yml 中 host、port、password 正确。

Q4:npm install 失败

原因:网络问题或 npm 版本问题。
解决:

bash

npm cache clean --force
npm install --registry=https://registry.npmmirror.com

Q5:前端页面空白 / API 请求 404

原因:后端未启动或代理配置问题。
解决:确保后端已启动,通过 npm run dev 启动前端(不要直接打开 index.html)。

Q6:端口被占用

原因:8080 或 3000 端口已被占用。
解决:

bash

netstat -ano | findstr :8080
# 或修改 application.yml 中的 server.port

九、项目亮点总结

9.1 后端亮点

  1. 完整的安全体系:Spring Security + JWT 无状态认证 + BCrypt 密码加密 + RBAC 角色权限 + CORS 跨域防护
  2. 双层缓存架构:Redis(分布式)+ Caffeine(本地缓存),兼顾性能与可扩展性
  3. 完善的异常处理:@RestControllerAdvice 全局异常捕获 + 统一 ApiResponse 响应格式
  4. RESTful API 设计:规范的路由命名、HTTP 方法语义化、统一的请求响应格式
  5. Swagger 文档:SpringDoc OpenAPI 自动生成,支持在线调试
  6. 文件管理:支持多格式上传、Content-Type 自动识别下载、文件大小校验
  7. 作业查重:内置文本相似度检测
  8. 成绩统计:自动计算平均分/最高分/最低分/提交率/批改率

9.2 前端亮点

  1. 现代技术栈:Vue 3 Composition API + Pinia + Vite 6
  2. 组件按需引入:unplugin-vue-components + unplugin-auto-import,无需手动 import
  3. 路由懒加载:所有页面组件动态 import,首屏加载快
  4. 代码分割:Element Plus、Vue 生态、ECharts 分别独立 chunk
  5. 请求拦截器:自动注入 Token、401 自动跳转登录、统一错误提示
  6. 路由权限守卫:结合 NProgress 进度条,页面切换流畅
  7. 响应式布局:基于 Element Plus 栅格系统,适配桌面和移动端
  8. 状态持久化:使用 js-cookie 持久化 Token 和用户信息

9.3 安全特性

安全措施 实现方式
认证安全 JWT 无状态认证,Token 24h / Refresh Token 7d
密码安全 BCrypt 加密存储
权限控制 RBAC 角色 + @PreAuthorize 方法级注解
SQL 注入防护 JPA/MyBatis Plus 参数化查询
XSS 防护 前端 Element Plus 自动转义
CORS 防护 后端白名单配置 + 前端 Vite Proxy
CSRF 防护 无状态 JWT,禁用 Session

十、待完善方向

  • 📌 富文本编辑器(作业描述支持 Markdown/富文本)
  • 📌 文件断点续传(大文件上传优化)
  • 📌 Excel 批量导入导出成绩(Apache POI 已引入,待实现页面)
  • 📌 邮件通知服务(截止提醒、成绩通知)
  • 📌 单元测试覆盖率提升(目标 80%+)
  • 📌 Docker 容器化部署
  • 📌 WebSocket 实时消息推送

十一、写在最后

这个项目从零搭建到功能完成,花了大约两个月的时间。作为毕设项目,它基本覆盖了企业级开发中的核心知识点:Spring Boot 3、Spring Security、JWT、Redis、Vue 3、Element Plus 等。

项目代码注释详细,每个类和方法都标注了功能说明,适合初学者学习和参考。

如果这个项目对你有所帮助,欢迎给个 Star ⭐,也欢迎提 Issue 交流!

🔗 GitHub:GitHub - heyige/online-homework-system: 基于SpringBoot的在线作业管理系统 - Online Homework Management System · GitHub


附录:角色页面权限矩阵

页面路径 Admin Teacher Student 说明
/dashboard 控制台首页
/profile 个人资料
/change-password 修改密码
/homework 作业列表
/homework/create 创建作业
/homework/:id/edit ✅(仅自己) 编辑作业
/submission 提交作业
/grade 批改列表
/grade/:submissionId 批改详情
/statistics 成绩统计
/messages 消息中心
/users 用户管理
/profile-requests ✅(审核) 申请审批

本文发布于 CSDN,作者:一孤程

更多推荐