代码沙箱Java原生实现
之前我们完成了快速的前端页面开发
重点是在后端
历史问题修复
Java原生代码沙箱实现
docker代码沙箱实现
解决历史遗留问题 代码编辑器切换语言失败
监听language属性 动态更改编辑器的语言
我们在这里实现的是一个线程形式的监听
watch(
() => props.language,
() => {
if (codeEditor.value) {
monaco.editor.setModelLanguage(
toRaw(codeEditor.value).getModel(),
props.language
);
}
}
);
代码沙箱只负责接收代码和输入
返回编译运行的结果
不负责判题 可以作为独立的项目/服务 提供给其他的需要执行代码的项目去使用
我们再来重新看一下这个接口
之后我们直接在配置中去修改
就行
以Java编程语言为主 带大家实现代码沙箱 重要的是学思想 学关键思想
新建一个Spring Boot Web项目
最终这个项目要提供一个能够执行代码 操作代码沙箱的接口
选择依赖
编辑启动配置
server:
port: 8090
写一个启动类
package work.bigdata1421.dduojcodesandbox.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController("/")
public class MainController {
@GetMapping("/health")
public String healthCheck(){
return "ok";
}
}
测试一下
利用插件生成http接口的调用
成功打印了ok
我们接下来要把之前写的代码沙箱部分代码转移到里面
把代码沙箱的请求信息 响应信息都弄过来
还有接口
package work.bigdata1421.dduojcodesandbox;
//代码沙箱接口的定义
import work.bigdata1421.dduojcodesandbox.model.ExecuteCodeRequest;
import work.bigdata1421.dduojcodesandbox.model.ExecuteCodeResponse;
public interface CodeSandbox {
ExecuteCodeResponse executeCode(ExecuteCodeRequest executeCodeRequest);
}
现在我们实现接口 就能自动实现了
原生 的 代码沙箱尽可能不借助第三方的库和依赖 用最干净最原始的方式实现代码沙箱
代码沙箱需要 接收代码 编译代码 执行代码
在java代码中使用javac编译完成的 执行代码使用java命令实现的
我们假定有这样一个程序
我们试一试怎么样去编译执行
这个代码并不是实际编译后的代码 是反编译后我们开发者可读的代码
就是我们的编译器实际还原出来的
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package work.bigdata1421.dduojcodesandbox;
public class SimpleCompute {
public SimpleCompute() {
}
public static void main(String[] var0) {
int var1 = Integer.parseInt(var0[0]);
int var2 = Integer.parseInt(var0[1]);
System.out.println(var1 + var2);
}
}
但是我们用 -java 命令去运行字节码文件时
会出现找不到主类Main的问题
这是因为运行的时候我们会把包名带进去
我们新创建一个类 目的是去掉包名
这样就能重新编译运行
public class SimpleCompute {
public static void main(String[] args) {
int a = Integer.parseInt(args[0]);
int b = Integer.parseInt(args[1]);
System.out.println(a + b);
}
}
这样进行操作
思考
为什么编译后的程序是中文乱码呢
命令行终端的编码是GBK 和java代码文件本身的编码 UTF-8 不一致 导致乱码
我们可以通过chcp命令查看编码 GBK是936
但是不建议大家改变终端编码来解决编译乱码 因为其他人运行你的代码还是要改变环境
你不能保证每一次都是在这个终端上启动的
兼容性很差
正确的编译代码
javac -encoding utf-8
执行
java cp
我们在编译运行过程中
不禁会思考
实际OJ系统中 对用户输入的代码会有一定要求 便于系统统一的管理
所以我们把用户输入的类名限制为Main
可以减少类名不一致的风险
public class Main {
public static void main(String[] args) {
int a = Integer.parseInt(args[0]);
int b = Integer.parseInt(args[1]);
System.out.println(a + b);
}
}