news 2026/5/14 9:32:51

手把手教你用SpringBoot+Vue3+Docker从零搭建一个在线OJ系统(附完整源码)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
手把手教你用SpringBoot+Vue3+Docker从零搭建一个在线OJ系统(附完整源码)

手把手教你用SpringBoot+Vue3+Docker从零搭建一个在线OJ系统

在编程竞赛和算法训练领域,在线判题系统(Online Judge,简称OJ)一直是开发者提升技能的重要工具。对于计算机专业学生和全栈开发者而言,从零构建一个OJ系统不仅能深入理解前后端协同开发流程,还能掌握Docker容器化等现代开发技术。本文将带你完整实现一个支持代码提交、实时判题、竞赛管理的OJ系统,所有代码均可直接用于毕业设计或个人项目。

1. 项目架构设计与技术选型

一个完整的OJ系统通常包含三大核心模块:前端用户界面、后端业务逻辑和判题沙箱环境。我们采用以下技术栈实现高内聚低耦合的架构:

  • 前端:Vue3 + TypeScript + Vite
  • 后端:SpringBoot 2.7 + MyBatis-Plus
  • 判题机:Docker + Linux内核隔离
  • 数据库:MySQL 8.0 + Redis缓存

系统工作流程如下图所示(代码实现部分将在后续章节展开):

用户提交代码 → 前端Vue收集 → 后端SpringBoot接收 → 存入任务队列 → Docker判题机拉取 → 安全执行 → 返回结果 → 前端展示

关键设计考量

  1. 前后端完全分离,通过RESTful API交互
  2. 判题过程必须隔离在沙箱环境中
  3. 支持C/C++/Java/Python等多语言判题
  4. 采用JWT进行用户认证

2. 开发环境准备与项目初始化

2.1 基础环境配置

确保本地开发环境已安装以下组件:

组件版本要求安装验证命令
JDK≥11java -version
Node.js≥16node -v
Docker≥20.10docker --version
MySQL≥8.0mysql --version
Redis≥6.0redis-cli ping

提示:建议使用Docker Desktop管理容器服务,Windows系统需开启WSL2支持

2.2 前后端项目初始化

后端SpringBoot项目

# 使用Spring Initializr创建项目 curl https://start.spring.io/starter.zip \ -d dependencies=web,mybatis-plus,mysql,redis,security \ -d javaVersion=11 \ -d packaging=jar \ -d artifactId=online-judge \ -o backend.zip

前端Vue3项目

npm init vue@latest frontend -- --template vue-ts cd frontend && npm install axios pinia element-plus

初始化后的项目结构应包含:

online-judge/ ├── backend/ # SpringBoot项目 │ ├── src/ │ └── pom.xml └── frontend/ # Vue3项目 ├── src/ └── package.json

3. 后端核心功能实现

3.1 数据库设计与JPA集成

创建主要业务表结构:

CREATE TABLE `problem` ( `id` BIGINT PRIMARY KEY AUTO_INCREMENT, `title` VARCHAR(255) NOT NULL, `description` TEXT, `time_limit` INT DEFAULT 1000, `memory_limit` INT DEFAULT 256 ); CREATE TABLE `submission` ( `id` BIGINT PRIMARY KEY AUTO_INCREMENT, `problem_id` BIGINT NOT NULL, `user_id` BIGINT NOT NULL, `code` TEXT NOT NULL, `language` ENUM('C','CPP','JAVA','PYTHON') NOT NULL, `status` ENUM('PENDING','ACCEPTED','WRONG_ANSWER') DEFAULT 'PENDING' );

SpringBoot中配置MyBatis-Plus:

@MapperScan("com.oj.mapper") @EnableTransactionManagement public class MybatisConfig { @Bean public MybatisPlusInterceptor paginationInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); return interceptor; } }

3.2 判题任务队列实现

使用Redis实现判题任务队列:

@Component public class JudgeQueue { private final RedisTemplate<String, Object> redisTemplate; private static final String QUEUE_KEY = "judge:queue"; public void push(Submission submission) { redisTemplate.opsForList().rightPush(QUEUE_KEY, submission); } public Submission pop() { return (Submission) redisTemplate.opsForList().leftPop(QUEUE_KEY); } }

4. Docker判题机深度集成

4.1 安全沙箱设计与实现

创建专用的判题Docker镜像:

FROM ubuntu:22.04 RUN apt-get update && apt-get install -y \ gcc g++ openjdk-17-jdk python3 RUN useradd -m runner && chmod 700 /home/runner USER runner WORKDIR /home/runner

判题核心流程代码示例:

public JudgeResult judge(Submission submission) { String containerId = createContainer(submission); try { compileCode(containerId, submission); return runTestCases(containerId, submission); } finally { stopContainer(containerId); } } private String createContainer(Submission submission) { String[] cmd = { "docker", "run", "-id", "--memory=" + submission.getMemoryLimit() + "m", "--cpus=1", "oj-judge-image" }; return executeCommand(cmd); }

4.2 资源限制与安全防护

通过Docker实现严格的资源隔离:

参数说明典型值
--memory最大内存使用量256m (Java需更大)
--cpusCPU核心限制1
--pids-limit防止fork炸弹64
--read-only文件系统只读true
--network网络隔离none

注意:必须禁用容器内的系统调用,可通过Seccomp配置文件实现

5. 前端功能模块开发

5.1 题目列表与编辑器集成

使用Monaco Editor实现代码编辑器:

import * as monaco from 'monaco-editor'; const editor = monaco.editor.create(document.getElementById('editor'), { value: '// 输入你的代码', language: 'cpp', theme: 'vs-dark', minimap: { enabled: false } });

5.2 实时判题结果展示

通过WebSocket实现实时结果推送:

<script setup> import { ref } from 'vue'; const results = ref([]); const socket = new WebSocket('ws://localhost:8080/judge/ws'); socket.onmessage = (event) => { results.value.push(JSON.parse(event.data)); }; </script>

6. 系统部署与性能优化

6.1 Docker Compose全栈部署

编写docker-compose.yml:

version: '3.8' services: backend: build: ./backend ports: ["8080:8080"] depends_on: [mysql, redis] frontend: build: ./frontend ports: ["5173:5173"] judge: build: ./judge privileged: true mysql: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: ${DB_PASSWORD} redis: image: redis:6-alpine

6.2 性能优化技巧

  1. 前端静态资源缓存

    location /assets { expires 1y; add_header Cache-Control "public"; }
  2. 后端接口响应优化

    @Cacheable(value = "problems", key = "#id") public Problem getProblemById(Long id) { return problemMapper.selectById(id); }
  3. 判题机负载均衡

    # 启动多个判题实例 docker-compose scale judge=3

7. 项目扩展与进阶方向

  1. 多语言支持:添加Rust、Go等新语言的判题支持
  2. 智能作弊检测:基于代码相似度算法
  3. 分布式判题:使用Kafka实现任务分发
  4. CI/CD集成:GitHub Actions自动化测试部署
# 示例:代码相似度检测(需在判题镜像中安装) from difflib import SequenceMatcher def similarity(a, b): return SequenceMatcher(None, a, b).ratio()

实际开发中遇到的一个典型问题是Java程序的内存计算差异,需要在Docker内存限制基础上增加JVM开销缓冲。经过多次测试,发现设置-XX:MaxRAMPercentage=70参数能有效平衡限制与稳定性。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/14 9:23:04

BetterNCM插件管理器:3步快速实现网易云音乐功能扩展的终极指南

BetterNCM插件管理器&#xff1a;3步快速实现网易云音乐功能扩展的终极指南 【免费下载链接】BetterNCM-Installer 一键安装 Better 系软件 项目地址: https://gitcode.com/gh_mirrors/be/BetterNCM-Installer BetterNCM插件管理器是一款专为网易云音乐PC客户端设计的强…

作者头像 李华
网站建设 2026/5/14 9:21:25

从零到一:AMBA总线协议APB与AHB核心机制与实战解析

1. AMBA总线协议入门指南 刚接触SoC设计的工程师常常会被各种总线协议搞得晕头转向。我第一次接触AMBA总线时也是一头雾水&#xff0c;直到后来在实际项目中踩过几次坑才真正理解它的精髓。AMBA(Advanced Microcontroller Bus Architecture)是ARM公司制定的一套片上通信标准&am…

作者头像 李华
网站建设 2026/5/14 9:20:46

GD32 TLI与STM32 LTDC对比:移植RGB屏驱动时要注意这几点

GD32 TLI与STM32 LTDC深度对比&#xff1a;RGB屏驱动移植避坑指南 对于习惯了STM32生态的开发者来说&#xff0c;GD32的TLI控制器和IPA加速器在寄存器命名、功能配置上存在不少"暗坑"。本文将结合实战经验&#xff0c;从信号极性配置到时序计算差异&#xff0c;逐一剖…

作者头像 李华