# oj-backend **Repository Path**: yhefan/oj-backend ## Basic Information - **Project Name**: oj-backend - **Description**: 基于SpringBoot + Redis + MQ + Docker的在线OJ判题平台,系统提供用例题目并支持 判题服务、用户可开通会员解锁题库和更频繁的提交、提交题目签到等 - **Primary Language**: Java - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2024-04-26 - **Last Updated**: 2024-09-26 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # LesCode判题平台项目(后端) 本项目主要模仿了力扣的一些基本功能 ## 项目开发流程 1. 项目介绍、项目调研、需求分析 2. 核心业务流程 3. 项目要做的功能(功能模块) 4. 技术选型(技术预研) 5. 项目初始化 6. 项目开发 7. 测试 8. 优化 9. 代码提交、代码审核 ### 判题模块: springMvC接受用户提交的信息,做完初步的校验后发送到消息队列中,即ojMessageProducer.sendMessage(String.valueOf(questionSubmitId));,之后在OjMessageConsumer中调用judgeServer的判题功能,进入判题功能后,分为三步: 1. 必要的校验+选择代码沙箱,选择代码沙箱这一步采用了静态工厂模式+spring配置化(yml文件中定义了codesandbox.type)的方式实现对多种代码沙箱的灵活调用。通过工厂模式得到CodeSandbox对象后,使用代理模式增强(项目中以此统一了日志操作)减少重复代码 本项目代理模式的具体细节:项目中定义的远程代码沙箱、示例代码沙箱、第三方代码沙箱以及代码沙箱的代理类均实现了同一接口‘CodeSandbox’代理类获得真实对象后先做增强,之后调用真实对象的方法。本代理类名为CodeSandboxProxy,只服务于代码沙箱,因此属于静态代理。 2. 根据提交的题目ID获取本题的输入用例,之后把提交的代码、语言类型、输入用例封装到一个专门的类中并作为参数交给👉代码沙箱代理类。(本项目默认采用远程代码沙箱,所以这方面涉及远程开发方面,后面再细讲) 3. 得到代码沙箱的允许结果⭐,开始判题(本项目有默认判题策略和java语言判题策略,考虑到如果后续添加其他的语言。因此采用策略模式代替if else独立封装了不同语言的判题算法),判题结束,更新提交结果。 判题模块结束。 ### 👉代码沙箱:代码沙箱接收到判题模块发来的参数 得到用户提交的代码和输入用例,执行流程分为以下5步: 1. 把用户代码保存为文件 关键步骤 File userCodeFile = FileUtil.writeString() 2. 编译文件,得到classs文件 javac -encoding utf-8 和文件的绝对路径组成一个字符串,使用Runtime类执行命令。 java.lang.Runtime 类提供了与Java应用程序运行时系统交互的方法。它允许程序启动运行时操作,比如执行外部进程、获取内存统计信息、调整垃圾回收行为等 3. 执行代码,获取输出结果 String.format("java -Dfile.encoding=UTF-8 -cp %s Main %s",文件路径,输入用例); 遍历输入用例,每次使用 java -Dfile.encoding=UTF-8 -cp %s Main %s 执行代码,允许结果收集到List中 4. 收集整理输出结果 根据上一步的允许结果得到运行的最大事件,并把用时最大值和输出结果封装并return ⭐给判题模块。 5. 文件清理 以上5步,将其模板化,即使用模板方法模式定义一套标准的代码沙箱流程,运行子类自行扩展部分流程,提高代码一致性并大幅简化代码public abstract class JavaCodeSandboxTemplate implements CodeSandbox ### 远程开发:选用linux远程开发,在虚拟机上安装centOS系统作为开发平台,拿到虚拟机的ip地址,使用IDEA Tools->Development创建远程连接,指定linux中项目部署路径,同步本地的代码到linux系统中。之后使用JetBrains远程开发连接Linux实时开发(直接在linux上开发,只不过这里提供了一个IDEA界面,不需要在两个系统界面来回跳) java操作Docker:Linux上安装docker后,引入docker-java依赖(提供DockerClient),使用java操作DockerClient,进行: 1. 拉取镜像openjdk:8-alpine 2. 创建容器(指定容器挂载目录,把本地的文件同步到容器中,可以让容器访问) 3. 启动容器 #### 统计提交次数:当月提交第一次时创建一个31字节的数组,已知一个字节8bit,可计数255,即当天最多提交255次。一个用户一个月只要提交过一次就固定消耗31字节 ### 主要功能图 ![输入图片说明](image.png) ![输入图片说明](image2.png) ![输入图片说明](image3.png) ![输入图片说明](image4.png)