当前位置: 首页 > 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…...

地震勘探——干扰波识别、井中地震时距曲线特点

目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波&#xff1a;可以用来解决所提出的地质任务的波&#xff1b;干扰波&#xff1a;所有妨碍辨认、追踪有效波的其他波。 地震勘探中&#xff0c;有效波和干扰波是相对的。例如&#xff0c;在反射波…...

golang循环变量捕获问题​​

在 Go 语言中&#xff0c;当在循环中启动协程&#xff08;goroutine&#xff09;时&#xff0c;如果在协程闭包中直接引用循环变量&#xff0c;可能会遇到一个常见的陷阱 - ​​循环变量捕获问题​​。让我详细解释一下&#xff1a; 问题背景 看这个代码片段&#xff1a; fo…...

Python:操作 Excel 折叠

💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...

大型活动交通拥堵治理的视觉算法应用

大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动&#xff08;如演唱会、马拉松赛事、高考中考等&#xff09;期间&#xff0c;城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例&#xff0c;暖城商圈曾因观众集中离场导致周边…...

【位运算】消失的两个数字(hard)

消失的两个数字&#xff08;hard&#xff09; 题⽬描述&#xff1a;解法&#xff08;位运算&#xff09;&#xff1a;Java 算法代码&#xff1a;更简便代码 题⽬链接&#xff1a;⾯试题 17.19. 消失的两个数字 题⽬描述&#xff1a; 给定⼀个数组&#xff0c;包含从 1 到 N 所有…...

【Go】3、Go语言进阶与依赖管理

前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课&#xff0c;做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程&#xff0c;它的核心机制是 Goroutine 协程、Channel 通道&#xff0c;并基于CSP&#xff08;Communicating Sequential Processes&#xff0…...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战

在现代战争中&#xff0c;电磁频谱已成为继陆、海、空、天之后的 “第五维战场”&#xff0c;雷达作为电磁频谱领域的关键装备&#xff0c;其干扰与抗干扰能力的较量&#xff0c;直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器&#xff0c;凭借数字射…...

select、poll、epoll 与 Reactor 模式

在高并发网络编程领域&#xff0c;高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表&#xff0c;以及基于它们实现的 Reactor 模式&#xff0c;为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。​ 一、I…...

DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”

目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...

Mysql中select查询语句的执行过程

目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析&#xff08;Parser&#xff09; 2.4、执行sql 1. 预处理&#xff08;Preprocessor&#xff09; 2. 查询优化器&#xff08;Optimizer&#xff09; 3. 执行器…...