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

Java在线OJ项目(三)、前后端交互API模块

Java在线OJ项目(三)、前后端交互API模块

    • 1. 客户端向服务器请求所有题目 或者 单个题目
        • 前端
            • 获取所有题目
            • 获取一个题目
        • 后端
    • 2. 后端读取前端提交的代码,进行编译运行,返回结果
        • 前端提交代码
        • 后端处理

1. 客户端向服务器请求所有题目 或者 单个题目

前端:通过problem的URL地址访问(如果没有其它参数,则是查询所有题目,如果有id参数,就是查询具体题目)
后端:返回题目的具体详情
在这里插入图片描述在这里插入图片描述

前端

获取所有题目
        <script>// 在页面加载的时候, 尝试从服务器获取题目列表. 通过 ajax 的方式来进行获取function getProblems() {// 1. 先通过 ajax 从服务器获取到题目列表. $.ajax({url: "problem",type: "GET",success: function(data, status) {// data 是响应的 body, status 是响应的状态码// 2. 把得到的响应数据给构造成 HTML 片段makeProblemTable(data);}})}// 通过这个函数来把数据转换成 HTML 页面片段function makeProblemTable(data) {let problemTable = document.querySelector("#problemTable");for (let problem of data) {let tr = document.createElement("tr");let tdId = document.createElement("td");tdId.innerHTML = problem.id;tr.appendChild(tdId);let tdTitle = document.createElement("td");let a = document.createElement("a");a.innerHTML = problem.title;a.href = 'problemDetail.html?id=' + problem.id;a.target = '_blank';tdTitle.appendChild(a);tr.appendChild(tdTitle);let tdLevel = document.createElement("td");tdLevel.innerHTML = problem.level;tr.appendChild(tdLevel);problemTable.appendChild(tr);}}getProblems();</script>
获取一个题目
<script>// 通过 ajax 从服务器获取到题目的详情function getProblem() {// 1. 通过 ajax 给服务器发送一个请求$.ajax({url: "problem" + location.search,type: "GET",success: function (data, status) {makeProblemDetail(data);}})}function makeProblemDetail(problem) {// 1. 获取到 problemDesc, 把题目详情填写进去let problemDesc = document.querySelector("#problemDesc");let h3 = document.createElement("h3");h3.innerHTML = problem.id + "." + problem.title + "_" + problem.levelproblemDesc.appendChild(h3);let pre = document.createElement("pre");let p = document.createElement("p");p.innerHTML = problem.description;pre.appendChild(p);problemDesc.appendChild(pre);// 2. 把代码的模板填写到编辑框中. // let codeEditor = document.querySelector("#codeEditor");// codeEditor.innerHTML = problem.templateCode;editor.setValue(problem.templateCode)
</script>

后端

package api;import com.fasterxml.jackson.databind.ObjectMapper;
import dao.Problem;
import dao.ProblemDAO;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;@WebServlet("/problem")
public class ProblemServlet extends HttpServlet {//ObjectMapper类(com.fasterxml.jackson.databind.ObjectMapper)是Jackson的主要类,它可以帮助我们快速的进行各个类型和Json类型的相互转换。private ObjectMapper objectMapper = new ObjectMapper();@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//设置返回的状态码 200表示成功resp.setStatus(200);//返回的数据类型resp.setContentType("application/json;charset=utf8");ProblemDAO problemDAO = new ProblemDAO();// 尝试获取 id 参数. 如果能获取到, 说明是获取题目详情; 如果不能获取到, 说明是获取题目列表.String idString = req.getParameter("id");if (idString == null || "".equals(idString)) {// 没有获取到 id 字段. 查询题目列表List<Problem> problems = problemDAO.selectAll();String respString = objectMapper.writeValueAsString(problems);resp.getWriter().write(respString);} else {// 获取到了题目 id. 查询题目详情Problem problem = problemDAO.selectOne(Integer.parseInt(idString));String respString = objectMapper.writeValueAsString(problem);resp.getWriter().write(respString);}}
}

2. 后端读取前端提交的代码,进行编译运行,返回结果

在这里插入图片描述

前端提交代码

<script>// 3. 给提交按钮注册一个点击事件let submitButton = document.querySelector("#submitButton");submitButton.onclick = function () {// 点击这个按钮, 就要进行提交. (把编辑框的内容给提交到服务器上)let body = {id: problem.id,// code: codeEditor.value,code: editor.getValue(),};$.ajax({type: "POST",url: "compile",data: JSON.stringify(body),success: function (data, status) {let problemResult = document.querySelector("#problemResult");if (data.error == 0) {// 编译运行没有问题, 把 stdout 显示到页面中problemResult.innerHTML = data.stdout;} else {// 编译运行没有问题, 把 reason 显示到页面中problemResult.innerHTML = data.reason;}}});}}</script>

后端处理

package api;import com.fasterxml.jackson.databind.ObjectMapper;
import common.CodeInValidException;
import common.ProblemNotFoundException;
import compile.Answer;
import compile.Question;
import compile.Task;
import dao.Problem;
import dao.ProblemDAO;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;@WebServlet("/compile")
public class CompileServlet extends HttpServlet {static class CompileRequest {public int id;public String code;}static class CompileResponse {// 约定 error 为 0 表示编译运行 ok, error 为 1 表示编译出错, error 为 2 表示运行异常(用户提交的代码异常了), 3 表示其他错误public int error;public String reason;public String stdout;}private ObjectMapper objectMapper = new ObjectMapper();//    {
//        "id": 2,
//        "code": "class Solution {\n    public int[] twoSum(int[] nums, int target) {\n        int[] a = {0, 1};\n        return a;\n    }\n}    "
//    }@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 临时加一下这个代码, 来获取到 SmartTomcat 的工作目录System.out.println("用户的当前工作目录: "+System.getProperty("user.dir"));CompileRequest compileRequest = null;CompileResponse compileResponse = new CompileResponse();try {resp.setStatus(200);resp.setContentType("application/json;charset=utf8");// 1. 先读取请求的正文. 别按照 JSON 格式进行解析String body = readBody(req);compileRequest = objectMapper.readValue(body, CompileRequest.class);// 2. 根据 id 从数据库中查找到题目的详情 => 得到测试用例代码ProblemDAO problemDAO = new ProblemDAO();Problem problem = problemDAO.selectOne(compileRequest.id);if (problem == null) {// 为了统一处理错误, 在这个地方抛出一个异常.throw new ProblemNotFoundException();}// testCode 是测试用例的代码String testCode = problem.getTestCode();// requestCode 是用户提交的代码String requestCode = compileRequest.code;// 3. 把用户提交的代码和测试用例代码, 给拼接成一个完整的代码.String finalCode = mergeCode(requestCode, testCode);if (finalCode == null) {throw new CodeInValidException();}// System.out.println(finalCode);// 4. 创建一个 Task 实例, 调用里面的 compileAndRun 来进行编译运行.Task task = new Task();Question question = new Question();question.setCode(finalCode);Answer answer = task.compileAndRun(question);// 5. 根据 Task 运行的结果, 包装成一个 HTTP 响应compileResponse.error = answer.getError();compileResponse.reason = answer.getReason();compileResponse.stdout = answer.getStdout();} catch (ProblemNotFoundException e) {// 处理题目没有找到的异常compileResponse.error = 3;compileResponse.reason = "没有找到指定的题目! id=" + compileRequest.id;} catch (CodeInValidException e) {compileResponse.error = 3;compileResponse.reason = "提交的代码不符合要求!";} finally {String respString = objectMapper.writeValueAsString(compileResponse);resp.getWriter().write(respString);}}private static String mergeCode(String requestCode, String testCode) {// 1. 查找 requestCode 中的最后一个 }int pos = requestCode.lastIndexOf("}");if (pos == -1) {// 说明提交的代码完全没有 } , 显然是非法的代码.return null;}// 2. 根据这个位置进行字符串截取String subStr = requestCode.substring(0, pos);// 3. 进行拼接return subStr + testCode + "\n}";}private static String readBody(HttpServletRequest req) throws UnsupportedEncodingException {// 1. 先根据 请求头 里面的 ContentLength 获取到 body 的长度(单位是字节)int contentLength = req.getContentLength();// 2. 按照这个长度准备好一个 byte[] .byte[] buffer = new byte[contentLength];// 3. 通过 req 里面的 getInputStream 方法, 获取到 body 的流对象.try (InputStream inputStream = req.getInputStream()) {// 4. 基于这个流对象, 读取内容, 然后把内容放到 byte[] 数组中即可.inputStream.read(buffer);} catch (IOException e) {e.printStackTrace();}// 5. 把这个 byte[] 的内容构造成一个 Stringreturn new String(buffer, "UTF8");}
}

相关文章:

Java在线OJ项目(三)、前后端交互API模块

Java在线OJ项目&#xff08;三&#xff09;、前后端交互API模块 1. 客户端向服务器请求所有题目 或者 单个题目前端获取所有题目获取一个题目 后端 2. 后端读取前端提交的代码&#xff0c;进行编译运行&#xff0c;返回结果前端提交代码后端处理 1. 客户端向服务器请求所有题目…...

项目——负载均衡在线OJ

目录 项目介绍开发环境所用技术项目宏观结构编写思路1. 编写compile_server1.1 编译模块编写1.2 运行功能1.3compile_runner 编译与运行1.4 编写compile_server.cpp调用compile_run模块&#xff0c;形成网络服务 2. 编写基于MVC的oj_server2.1 oj_server.cpp的编写2.2 oj_model…...

idea连接远程服务器上传war包文件

idea连接远程服务器&上传war包 文章目录 idea连接远程服务器&上传war包1. 连接服务器2.上传war包 1. 连接服务器 选择Tools -> Start SSH Session 添加配置 连接成功 2.上传war包 Tools -> Deployment -> Browse Remote Host 点击右侧标签&#xff0c;点击&…...

使用PyGWalker可视化分析表格型数据

大家好&#xff0c;可以想象一下在Jupyter Notebook中拥有大量数据&#xff0c;想要对其进行分析和可视化。PyGWalker就像一个神奇的工具&#xff0c;能让这项工作变得超级简单。它能获取用户的数据&#xff0c;并将其转化为一种特殊的表格&#xff0c;可以与之交互&#xff0c…...

Visual C++中的虚函数和纯虚函数(以外观设计模式为例)

我是荔园微风&#xff0c;作为一名在IT界整整25年的老兵&#xff0c;今天来说说Visual C中的虚函数和纯虚函数。该系列帖子全部使用我本人自创的对比学习法。也就是当C学不下去的时候&#xff0c;就用JAVA实现同样的代码&#xff0c;然后再用对比的方法把C学会。 直接说虚函数…...

电子元器件选型与实战应用—01 电阻选型

大家好, 我是记得诚。 这是《电子元器件选型与实战应用》专栏的第一篇文章,今天的主角是电阻,在每一个电子产品中,都少不了电阻的身影,其重要性不言而喻。 文章目录 1. 入门知识1.1 基础1.2 常用品牌1.3 电阻的种类2. 贴片电阻标识2.1 三位数标注法2.2 四位数标注法2.3 小…...

javascript 模板引擎

使用场景 在实际开发中&#xff0c;一般都是使用动态请求数据来更新页面&#xff0c;服务器端通常返回json格式的数据&#xff0c;正常操作是我们手动的去拼装HTML&#xff0c;但麻烦且容易出错&#xff0c;因此出现了一些用模版生成HTML的的框架叫js模板引擎如&#xff1a;jq…...

【数据结构】带头+双向+循环链表(DList)(增、删、查、改)详解

一、带头双向循环链表的定义和结构 1、定义 带头双向循环链表&#xff0c;有一个数据域和两个指针域。一个是前驱指针&#xff0c;指向其前一个节点&#xff1b;一个是后继指针&#xff0c;指向其后一个节点。 // 定义双向链表的节点 typedef struct ListNode {LTDataType dat…...

接口自动化测试平台

下载了大神的EasyTest项目demo修改了下<https://testerhome.com/topics/12648 原地址>。也有看另一位大神的HttpRunnerManager<https://github.com/HttpRunner/HttpRunnerManager 原地址>&#xff0c;由于水平有限&#xff0c;感觉有点复杂~~~ 【整整200集】超超超…...

【物联网】微信小程序接入阿里云物联网平台

微信小程序接入阿里云物联网平台 一 阿里云平台端 1.登录阿里云 阿里云物联网平台 点击进入公共实例&#xff0c;之前没有的点进去申请 2.点击产品&#xff0c;创建产品 3.产品名称自定义&#xff0c;按项目选择类型&#xff0c;节点类型选择之恋设备&#xff0c;联网方式W…...

PKG内容查看工具:Suspicious Package for Mac安装教程

Suspicious Package Mac版是一款Mac平台上的查看 PKG 程序包内信息的应用&#xff0c;Suspicious Package Mac版支持查看全部包内全部文件&#xff0c;比如需要运行的脚本&#xff0c;开发者&#xff0c;来源等等。 suspicious package mac使用简单&#xff0c;只需在选择pkg安…...

第16节:R语言医学分析实例:肺切除手术的Apriori关联规则分析

关联规则 肺切除手术的Apriori关联规则分析。 分析的目的是确定患有肺癌并需要接受肺切除术的患者的共病症状。 了解哪些症状是共病的可以帮助改善患者护理和药物处方。 分析类型是关联规则学习,通过探索变量之间的关联或频繁项集,尝试在大型数据集中找到见解和隐藏关系(H…...

ChatGPT+MidJourney 3分钟生成你的动画故事

chatgpt是真的火了&#xff0c;chatgpt产生了一个划时代的意义——自chatgpt起&#xff0c;AI是真的要落地了。 chatgpt能做的事情太多了&#xff0c;多到最初开发模型的程序员自己&#xff0c;也没法说得清楚chatgpt都能做啥&#xff0c;似乎只要你能想得到&#xff0c;它都有…...

在CSDN学Golang云原生(Kubernetes Pod调度)

一&#xff0c;NodeSelector定向调度 在 Kubernetes 中&#xff0c;可以使用 NodeSelector 字段来指定 Pod 调度到哪些节点上运行。NodeSelector 是一个键值对的 map&#xff0c;其中键是节点的标签名&#xff0c;值是标签值。具体步骤如下&#xff1a; 在节点上添加标签 首…...

Rust vs Go:常用语法对比(七)

题图来自 Go vs Rust: Which will be the top pick in programming?[1] 121. UDP listen and read Listen UDP traffic on port p and read 1024 bytes into buffer b. 听端口p上的UDP流量&#xff0c;并将1024字节读入缓冲区b。 import ( "fmt" "net&qu…...

【HarmonyOS】API6使用storage实现轻量级数据存储

写在前面 本篇内容基于API6 JS语言进行开发&#xff0c;通过结合轻量级数据存储开发指导的文档&#xff0c;帮助大家完成一个实际的代码案例&#xff0c;通过这个小案例&#xff0c;可以实现简单数据的存储。 参考文档&#xff1a;文档中心 1、页面布局 首先我们编写一个简单…...

Python Flask构建微信小程序订餐系统 (十二)

🔥 创建切换商品分类状态的JS文件 🔥 ; var food_act_ops={init:function(){this.eventBind();},eventBind:function(){//表示作用域var that = this;$(".wrap_search select[name=status]").change(function(){$(".wrap_search").submit();});$(&qu…...

C++——模板的作用2:特例化

目录 模板的形式&#xff1a; 一.模板的多参数应用&#xff1a; 例&#xff1a; 错误使用1&#xff1a;使用不标准的模板形参表 ​编辑 错误使用2&#xff1a;使用变量作为实参传递给函数模板 二.模板的特例化&#xff1a; 类模板&#xff1a; 针对模板的特化步骤&am…...

Python Web开发技巧VII

目录 装饰器inject_serializer 装饰器atomic rebase git 清理add的数据 查看git的当前工作目录 makemigrations文件名称 action(detailTrue, methods["GET"]) 如何只取序列化器的一个字段进行返回 Response和JsonResponse有什么区别 序列化器填表和单字段如…...

LaTex4【下载模板、引入文献】

下载latex模板&#xff1a;&#xff08;模板官网一般都有&#xff0c;去找&#xff09; 我这随便找了一个&#xff1a; 下载得到一个压缩包&#xff0c;然后用overleaf打开&#x1f447;&#xff1a; (然后改里面的内容就好啦) 另外&#xff0c;有很多在线的数学公式编辑器&am…...

【入坑系列】TiDB 强制索引在不同库下不生效问题

文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...

使用分级同态加密防御梯度泄漏

抽象 联邦学习 &#xff08;FL&#xff09; 支持跨分布式客户端进行协作模型训练&#xff0c;而无需共享原始数据&#xff0c;这使其成为在互联和自动驾驶汽车 &#xff08;CAV&#xff09; 等领域保护隐私的机器学习的一种很有前途的方法。然而&#xff0c;最近的研究表明&…...

iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版​分享

平时用 iPhone 的时候&#xff0c;难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵&#xff0c;或者买了二手 iPhone 却被原来的 iCloud 账号锁住&#xff0c;这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...

Go 语言接口详解

Go 语言接口详解 核心概念 接口定义 在 Go 语言中&#xff0c;接口是一种抽象类型&#xff0c;它定义了一组方法的集合&#xff1a; // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的&#xff1a; // 矩形结构体…...

[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?

论文网址&#xff1a;pdf 英文是纯手打的&#xff01;论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误&#xff0c;若有发现欢迎评论指正&#xff01;文章偏向于笔记&#xff0c;谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)

设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile&#xff0c;新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包

文章目录 现象&#xff1a;mysql已经安装&#xff0c;但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时&#xff0c;可能是因为以下几个原因&#xff1a;1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...

C++.OpenGL (20/64)混合(Blending)

混合(Blending) 透明效果核心原理 #mermaid-svg-SWG0UzVfJms7Sm3e {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-icon{fill:#552222;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-text{fill…...

Python+ZeroMQ实战:智能车辆状态监控与模拟模式自动切换

目录 关键点 技术实现1 技术实现2 摘要&#xff1a; 本文将介绍如何利用Python和ZeroMQ消息队列构建一个智能车辆状态监控系统。系统能够根据时间策略自动切换驾驶模式&#xff08;自动驾驶、人工驾驶、远程驾驶、主动安全&#xff09;&#xff0c;并通过实时消息推送更新车…...

Caliper 配置文件解析:fisco-bcos.json

config.yaml 文件 config.yaml 是 Caliper 的主配置文件,通常包含以下内容: test:name: fisco-bcos-test # 测试名称description: Performance test of FISCO-BCOS # 测试描述workers:type: local # 工作进程类型number: 5 # 工作进程数量monitor:type: - docker- pro…...