当前位置: 首页 > news >正文

OJ在线评测系统 后端 判题机模块预开发 架构分析 使用工厂模式搭建

判题机模块预开发(架构师)(工厂模式)

判题机模块

是为了把代码交个代码沙箱去处理 得到结果返回

代码沙箱

梳理判题模块和代码沙箱的关系

判题模块:调用代码沙箱 把代码和输入交给代码沙箱去执行

代码沙箱:只负责接受代码和输入 返回编译的结果 不负责判题

这两个模块完全解耦

我们采用API交互

为什么代码沙箱要接受和输出一组运行用例

前提:我们的每道题目有多组测试用例

如果每个用例单独调用一个代码用例 会调用多次接口 需要多次网络运输 程序要多次编译 记录程序的执行状态 重复的代码不重复编译

这是一种常见的性能优化的方法

创建一个新的包

用来放代码沙箱模块

先写一个接口

package com.dduo.dduoj.judge.codesandbox;public interface CodeSandbox {ExecuteCodeRequest executeCode(ExecuteCodeRequest executeCodeRequest);
}

提高通用性

之后我们的项目代码只调用接口

不调用具体的实现类

就不用去修改名称了 便于拓展

写一下实体类

ExecuteCodeRequest请求

package com.dduo.dduoj.judge.codesandbox.model;import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;import java.util.List;@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ExecuteCodeRequest {private List<String> inputList;private String code;private String language;
}


ExecuteCodeResponse响应

package com.dduo.dduoj.judge.codesandbox.model;import com.dduo.dduoj.model.dto.question.JudgeConfig;
import com.dduo.dduoj.model.dto.questionsubmit.JudgeInfo;import java.util.List;public class ExecuteCodeResponse {private List<String> outputList;//执行信息private String message;//执行状态private Integer status;private JudgeInfo judgeInfo;
}

完善

定义不同的代码沙箱实现类

示例代码沙箱

远程代码沙箱

第三方代码沙箱

架构工作

lombok Builder注解

测试一下

package com.dduo.dduoj.judge.codesandbox;import com.dduo.dduoj.judge.codesandbox.impl.ExampleCodeSandbox;
import com.dduo.dduoj.judge.codesandbox.impl.RemoteCodeSandbox;
import com.dduo.dduoj.judge.codesandbox.model.ExecuteCodeRequest;
import com.dduo.dduoj.judge.codesandbox.model.ExecuteCodeResponse;import com.dduo.dduoj.model.enums.QuestionSubmitLanguageEnum;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;import java.util.Arrays;
import java.util.List;@SpringBootTest
class CodeSandboxTest {@Testvoid executeCode() {CodeSandbox codeSandbox = new RemoteCodeSandbox();String code = "int main() { }";String language = QuestionSubmitLanguageEnum.JAVA.getValue();List<String> inputList = Arrays.asList("1 2", "3 4");ExecuteCodeRequest executeCodeRequest = ExecuteCodeRequest.builder().code(code).language(language).inputList(inputList).build();ExecuteCodeResponse executeCodeResponse = codeSandbox.executeCode(executeCodeRequest);Assertions.assertNotNull(executeCodeResponse);}
}

工厂模式

但是现在问题是我们把new代码沙箱写死了 如果后面项目要改用其他沙箱

可能要改很多地方的代码

我们要使用工厂模式

根据用具传入的字符串参数 生成对应的代码沙箱实现类

package com.dduo.dduoj.judge.codesandbox;import com.dduo.dduoj.judge.codesandbox.impl.ExampleCodeSandbox;
import com.dduo.dduoj.judge.codesandbox.impl.RemoteCodeSandbox;
import com.dduo.dduoj.judge.codesandbox.impl.ThirdPartyCodeSandbox;//代码沙箱工厂 根据字符串参数 创建指定的代码沙箱示例
public class CodeSandboxFactory {/** 创建代码沙箱示例* @param type 沙箱类型* @return* */public static CodeSandbox NewInstance(String type) {switch (type) {case "example":return new ExampleCodeSandbox();case "remote":return new RemoteCodeSandbox();case "thirdParty":return new ThirdPartyCodeSandbox();default:return new ExampleCodeSandbox();}}
}

如果确定代码沙箱示例不会出现线程安全问题

可复用

那么可以使用单例工厂模式

但是这种方式是不可取的 我们应该把这些东西放到配置里面

配置化 去改配置文件 而不是修改字符串

这就叫参数配置化 开发者只需要去修改配置文件 而不是去看项目代码 就能自定义使用项目的更多功能

先在application.yml里面去设置

再在程序里面去读取

示例

package com.dduo.dduoj.judge.codesandbox;import com.dduo.dduoj.judge.codesandbox.impl.ExampleCodeSandbox;
import com.dduo.dduoj.judge.codesandbox.impl.RemoteCodeSandbox;
import com.dduo.dduoj.judge.codesandbox.model.ExecuteCodeRequest;
import com.dduo.dduoj.judge.codesandbox.model.ExecuteCodeResponse;import com.dduo.dduoj.model.enums.QuestionSubmitLanguageEnum;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;import java.util.Arrays;
import java.util.List;@SpringBootTest
class CodeSandboxTest {@Value("${codesandbox.type:example}")private String value;@Testvoid executeCode() {CodeSandbox codeSandbox = CodeSandboxFactory.NewInstance(value);String code = "int main() { }";String language = QuestionSubmitLanguageEnum.JAVA.getValue();List<String> inputList = Arrays.asList("1 2", "3 4");ExecuteCodeRequest executeCodeRequest = ExecuteCodeRequest.builder().code(code).language(language).inputList(inputList).build();ExecuteCodeResponse executeCodeResponse = codeSandbox.executeCode(executeCodeRequest);Assertions.assertNotNull(executeCodeResponse);}
}

我们要增强代码沙箱的能力

在调用代码沙箱前 输出请求参数 在代码沙箱调用后 输出响应结果日志

package com.dduo.dduoj.judge.codesandbox.impl;import com.dduo.dduoj.judge.codesandbox.CodeSandbox;
import com.dduo.dduoj.judge.codesandbox.model.ExecuteCodeRequest;
import com.dduo.dduoj.judge.codesandbox.model.ExecuteCodeResponse;
import lombok.extern.slf4j.Slf4j;//示例代码沙箱 (仅供测试 跑通业务流程)
@Slf4j
public class ExampleCodeSandbox implements CodeSandbox {@Overridepublic ExecuteCodeResponse executeCode(ExecuteCodeRequest executeCodeRequest) {log.info("请求信息"+executeCodeRequest.toString());System.out.println("示例代码沙箱");return null;}
}

思考

我们每一个代码沙箱类都写一个 log.info ?

难道每次调用代码沙箱前后都要执行log ?

我们使用代理模式 提供一个Proxy 来增强代码沙箱的能力

静态代理模式

中介

调用者调用代理类 代理类去调用代码沙箱

代理类还可以做一些额外的功能

不仅不用改变原本的代码沙箱实现类 而且对调用者来说 基本也没有改变

也不需要在每一个调用代码沙箱的地方去统计代码

package com.dduo.dduoj.judge.codesandbox;import com.dduo.dduoj.judge.codesandbox.model.ExecuteCodeRequest;
import com.dduo.dduoj.judge.codesandbox.model.ExecuteCodeResponse;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;@Slf4j
@AllArgsConstructor
public class CodeSandboxProxy implements CodeSandbox{private CodeSandbox codeSandbox;@Overridepublic ExecuteCodeResponse executeCode(ExecuteCodeRequest executeCodeRequest) {log.info("代码沙箱的请求信息"+executeCodeRequest.toString());ExecuteCodeResponse executeCodeResponse = codeSandbox.executeCode(executeCodeRequest);log.info("代码沙箱的响应信息"+executeCodeResponse.toString());return executeCodeResponse;}
}

接下来我们就可以去修改调用方式

@Test
void executeCodeByProxy() {CodeSandbox codeSandbox = CodeSandboxFactory.NewInstance(value);codeSandbox =new CodeSandboxProxy(codeSandbox);String code = "int main() { }";String language = QuestionSubmitLanguageEnum.JAVA.getValue();List<String> inputList = Arrays.asList("1 2", "3 4");ExecuteCodeRequest executeCodeRequest = ExecuteCodeRequest.builder().code(code).language(language).inputList(inputList).build();ExecuteCodeResponse executeCodeResponse = codeSandbox.executeCode(executeCodeRequest);Assertions.assertNotNull(executeCodeResponse);
}

相关文章:

OJ在线评测系统 后端 判题机模块预开发 架构分析 使用工厂模式搭建

判题机模块预开发(架构师)(工厂模式) 判题机模块 是为了把代码交个代码沙箱去处理 得到结果返回 代码沙箱 梳理判题模块和代码沙箱的关系 判题模块&#xff1a;调用代码沙箱 把代码和输入交给代码沙箱去执行 代码沙箱&#xff1a;只负责接受代码和输入 返回编译的结果 不负…...

linux 目录文件夹操作

目录 查看文件夹大小&#xff1a; Linux统计文件个数 2.统计文件夹中文件个数ls -l ./|grep "^-"|wc -l 4.统计文件夹下文件个数&#xff0c;包括子文件ls -lR | grep "^-"| wc -l 统计文件个数 移动绝对目录&#xff1a; 移动相对目录 test.py报错…...

(Linux驱动学习 - 4).Linux 下 DHT11 温湿度传感器驱动编写

DHT11的通信协议是单总线协议&#xff0c;可以用之前学习的pinctl和gpio子系统完成某IO引脚上数据的读与写。 一.在设备树下添加dht11的设备结点 1.流程图 2.设备树代码 &#xff08;1&#xff09;.在设备树的 iomuxc结点下添加 pinctl_dht11 &#xff08;2&#xff09;.在根…...

前端登录页面验证码

首先&#xff0c;在el-form-item里有两个div&#xff0c;各占一半&#xff0c;左边填验证码&#xff0c;右边生成验证码 <el-form-item prop"code"><div style"display: flex " prop"code"><el-input placeholder"请输入验证…...

【鸿蒙】HarmonyOS NEXT应用开发快速入门教程之布局篇(上)

系列文章目录 【鸿蒙】HarmonyOS NEXT开发快速入门教程之ArkTS语法装饰器&#xff08;上&#xff09; 【鸿蒙】HarmonyOS NEXT开发快速入门教程之ArkTS语法装饰器&#xff08;下&#xff09; 【鸿蒙】HarmonyOS NEXT应用开发快速入门教程之布局篇&#xff08;上&#xff09; 文…...

使用 Nginx 和 Gunicorn 部署 Flask 项目详细教程

使用 Nginx 和 Gunicorn 部署 Flask 项目详细教程 在这篇文章中&#xff0c;我们将介绍如何使用 Nginx 和 Gunicorn 来部署一个 Flask 项目。这种部署方式非常适合在生产环境中使用&#xff0c;因为它能够提供更好的性能和更高的稳定性。 目录 Flask 项目简介环境准备Gunico…...

linux中bashrc和profile环境变量在Shell编程变量的传递作用

在 Linux 系统中&#xff0c;.bashrc文件和.profile文件都是用于配置用户环境的重要文件&#xff0c;它们之间有以下关联&#xff1a; 一、作用相似性 环境设置&#xff1a;两者都用于设置用户的环境变量和启动应用程序的配置。例如&#xff0c;它们可以定义路径变量&#xf…...

数据结构-4.2.串的定义和基本操作

一.串的定义&#xff1a; 1.单/双引号不是字符串里的内容&#xff0c;他只是一个边界符&#xff0c;用来表示字符串的头和尾&#xff1b; 2.空串也是字符串的子串&#xff0c;空串长度为0&#xff1b; 3.字符的编号是从1开始&#xff0c;不是0&#xff1b; 4.空格也是字符&a…...

fastzdp_redis第一次开发, 2024年9月26日, Python操作Redis零基础快速入门

提供完整录播课 安装 pip install fastzdp_redisPython连接Redis import redis# 建立链接 r redis.Redis(hostlocalhost, port6379, db0)# 设置key r.set(foo, bar)# 获取key的值 print(r.get(foo))RESP3 支持 简单的理解: 支持更丰富的数据类型 参考文档: https://blog.c…...

文件名:\\?\C:\Windows\system32\inetsrv\config\applicationHost.config错误:无法写入配置文件

文件名: \\?\C:\Windows\system32\inetsrv\config\applicationHost.config 错误:无法写入配置文件 解决办法&#xff1a; 到C:\inetpub\history中找到最近一次的【CFGHISTORY_00000000XX】文件&#xff0c;点击进去找到applicationHost.config文件&#xff0c;用其覆盖C:\Win…...

Optiver股票大赛Top2开源!

Optiver股票大赛Top2开源&#xff01; ↑↑↑关注后"星标"kaggle竞赛宝典 作者&#xff1a;杰少 Optiver第二名方案解读 简介 Optiver竞赛已经于今天结束了&#xff0c;竞赛也出现了极端情况&#xff0c;中间断崖式的情况&#xff0c;在Kaggle过往的竞赛中&#…...

Maven 实现依赖统一管理

Maven 实现依赖统一管理主要是通过两个关键机制&#xff1a;pom.xml 文件中的 <dependencies> 节点用于声明项目依赖&#xff0c;以及通过继承&#xff08;Inheritance&#xff09;和聚合&#xff08;Aggregation&#xff09;功能来统一管理和组织这些依赖。此外&#xf…...

【最新】微信小程序连接onenet——stm32+esp8266+onenet实现查看温湿度,控制单片机

微信小程序——stm32esp8266onenet实现查看温湿度&#xff0c;控制单片机 &#xff08;最新已验证&#xff09;stm32 新版 onenet dht11esp8266/01s mqtt物联网上报温湿度和控制单片机(保姆级教程) &#xff1a;↓↓&#x1f447; &#x1f447; &#x1f447; &#x1f447…...

差分(续前缀和)(含一维二维)

题目引入 开发商小 Q 买下了一条街&#xff0c;他想在这条街的一边盖房子。 街道可以抽象为一条数轴&#xff0c;而小 Q 只会在坐标在 1~n 的范围内盖房子。 首先&#xff0c;小 Q 将街上坐标在 1∼ &#x1d45b;1∼ n 范围内的物体全部铲平。也就是说&#xff0c;在正式动工盖…...

【STM32-HAL库】自发电型风速传感器(使用STM32F407ZGT6)(附带工程下载链接)

一、自发电型风速传感器介绍 自发电型风速传感器&#xff0c;也称为风力发电型风速传感器或无源风速传感器&#xff0c;是一种不需要外部电源即可工作的风速测量设备。这种传感器通常利用风力来驱动内部的发电机构&#xff0c;从而产生电能来供电测量风速的传感器部分。以下是自…...

【计算机毕业设计】springboot就业信息管理系统

就业信息管理系统 摘 要 随着信息化时代的到来&#xff0c;管理系统都趋向于智能化、系统化&#xff0c;就业信息管理系统也不例外&#xff0c;但目前国内仍都使用人工管理&#xff0c;市场规模越来越大&#xff0c;同时信息量也越来越庞大&#xff0c;人工管理显然已无法应对时…...

实用工具推荐---- PDF 转换

直接上链接&#xff1a;爱PDF |面向 PDF 爱好者的在线 PDF 工具 (ilovepdf.com) 主要功能如下&#xff1a; 全免费&#xff01;&#xff01;&#xff01;&#xff01;...

安宝特案例 | 某知名日系汽车制造厂,借助AR实现智慧化转型

案例介绍 在全球制造业加速数字化的背景下&#xff0c;工厂的生产管理与设备维护效率愈发重要。 某知名日系汽车制造厂当前面临着设备的实时监控、故障维护&#xff0c;以及跨地域的管理协作等挑战&#xff0c;由于场地分散和突发状况的不可预知性&#xff0c;传统方式已无法…...

RabbitMQ基本原理

一、基本结构 所有中间件技术都是基于 TCP/IP 协议基础之上进行构建新的协议规范&#xff0c;RabbitMQ遵循的是AMQP协议&#xff08;Advanced Message Queuing Protocol - 高级消息队列协议&#xff09;。 生产者发送消息流程&#xff1a; 1、生产者和Broker建立TCP连接&#…...

【NodeJS】npm、yarn、pnpm当前项目设置国内镜像源

全局设置镜像源&#xff0c;可以参考下这篇文章&#xff0c;还挺详细&#xff1a;《npm、yarn、pnpm 最新国内镜像源设置和常见问题解决》 临时设置镜像源&#xff1a;《npm永久或临时切换源》 有时候可能要同时多个开发项目&#xff0c;又不想修改全局的镜像源(具体场景…自行…...

如何用PortProxyGUI简化Windows端口转发配置

如何用PortProxyGUI简化Windows端口转发配置 【免费下载链接】PortProxyGUI A manager of netsh interface portproxy which is to evaluate TCP/IP port redirect on windows. 项目地址: https://gitcode.com/gh_mirrors/po/PortProxyGUI PortProxyGUI是一款专为Window…...

VAP;SNTRVAP

一、基本信息名称&#xff1a;VAP peptide单字母序列&#xff1a;SNTRVAP三字母序列&#xff1a;Ser-Asn-Thr-Arg-Val-Ala-Pro长度&#xff1a;7 个氨基酸&#xff08;7‑mer&#xff09;类型&#xff1a;线性多肽&#xff0c;无 Cys、无 Met、无 Trp&#xff0c;氧化稳定性极佳…...

CosyVoice Docker 部署优化:如何有效降低 CPU 占用率

在语音合成服务日益普及的今天&#xff0c;CosyVoice 凭借其出色的音质和灵活性&#xff0c;成为了许多开发者的选择。然而&#xff0c;当我们将它部署到 Docker 容器中时&#xff0c;一个普遍且棘手的问题随之而来&#xff1a;CPU 占用率居高不下。这不仅导致服务器资源成本飙…...

告别风扇噪音与过热:FanControl智能控温完全指南

告别风扇噪音与过热&#xff1a;FanControl智能控温完全指南 【免费下载链接】FanControl.Releases This is the release repository for Fan Control, a highly customizable fan controlling software for Windows. 项目地址: https://gitcode.com/GitHub_Trending/fa/FanC…...

效率直接起飞!盘点2026年全网顶尖的AI论文工具

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂的AI论文工具&#xff0c;实测提速效果惊人&#xff0c;覆盖选题构思、文献整理、内容生成、格式排版全流程&#xff0c;让你高效搞定论文&#xff0c;告别熬夜赶工。 一、全流程王者&#xff1a;一站式搞定论文全链路&…...

利用快马AI三分钟生成Python哈希表原型,快速验证数据存储方案

今天在做一个数据处理的小项目时&#xff0c;突然需要快速验证一个数据存储方案。想到哈希表这种高效的数据结构正好适合&#xff0c;但自己从头实现又太费时间。正好最近在用InsCode(快马)平台&#xff0c;发现它的AI辅助功能可以快速生成可运行的原型代码&#xff0c;于是尝试…...

从零部署JetLinks社区版:一站式物联网平台本地化搭建实战

1. JetLinks社区版&#xff1a;物联网开发的瑞士军刀 第一次接触JetLinks社区版是在三年前的一个智能家居项目上。当时客户要求两周内搭建一个能管理5000设备的物联网平台&#xff0c;还要支持自定义协议开发。在对比了多个开源方案后&#xff0c;JetLinks的模块化设计让我眼前…...

Steam致命错误failed to load steamui.dll?小白必看的6种实用修复方案

软件获取地址 https://pan.quark.cn/s/4cc6a4c0e881 打开Steam时突然弹出“failed to load steamui.dll”提示&#xff0c;无法进入平台甚至启动Y戏&#xff1f;这是Steam最常见的致命错误之一&#xff0c;在failed to load类问题中占比超4成&#xff0c;很多小白不清楚dll文件…...

如何选择最适合的开源付费墙绕过工具?5款热门方案深度测评

如何选择最适合的开源付费墙绕过工具&#xff1f;5款热门方案深度测评 【免费下载链接】bypass-paywalls-chrome-clean 项目地址: https://gitcode.com/GitHub_Trending/by/bypass-paywalls-chrome-clean 在数字内容付费阅读日益普及的今天&#xff0c;开源工具为用户提…...

Ostrakon-VL-8B零基础上手:无需代码,5分钟完成门店图片智能分析

Ostrakon-VL-8B零基础上手&#xff1a;无需代码&#xff0c;5分钟完成门店图片智能分析 1. 引言 想象一下&#xff0c;你是一家连锁便利店的区域经理&#xff0c;手下管着几十家门店。每周巡店检查&#xff0c;光是看照片、数货架、查价格标签&#xff0c;就要花掉大半天时间…...