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

news/2024/5/18 17:32:47

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");}
}

http://www.mrgr.cn/p/05340844

相关文章

IntelliJ IDEA 2023.2 最新变化

主要更新 AI Assistant 限定访问 Ultimate 在此版本中&#xff0c;我们为 IntelliJ IDEA 引入了一项重要补充 – AI Assistant。 AI Assistant 当前具备一组由 AI 提供支持的初始功能&#xff0c;提供集成式 AI 聊天&#xff0c;可以完成一些任务&#xff0c;例如自动编写文档…

【7.31】C++编写7254是一个不寻常的数,可以表示为7254 = 39 x 186,这个式子中1~9每个数字正好出现一次

题目题干 7254是一个不寻常的数&#xff0c;因为它可以表示为7254 39 x 186&#xff0c;这个式子中1~9每个数字正好出现一次&#xff0c;输出所有这样的不同的式子&#xff08;乘数交换被认为是相同的式子&#xff09;。结果小的先输出&#xff1b;结果相同的&#xff0c;较小…

Vue+Nodejs+Express+Minio 实现本地图片上传

安装Minio,Minio server和Minio client都要下载可以自定义安装目录 安装完成之后,可以将minio配置成环境变量方便使用 配置了环境变量启动命令式 minio server start,默认账号密码minioadmin和minioadmin,点击9000端口的这个链接,即可访问客户端 nodejs连接Minio,简易服务进…

机器学习深度学习——多层感知机

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位即将上大四&#xff0c;正专攻机器学习的保研er &#x1f30c;上期文章&#xff1a;机器学习&&深度学习——感知机 &#x1f4da;订阅专栏&#xff1a;机器学习&&深度学习 希望文章对你们有所帮助 上一节…

如何优雅的显示404页面

源码&#xff1a;mumangguo/404-notfound - 码云 - 开源中国https://gitee.com/mumangguo/404-notfound 1.孤独型404页面 2.酷炫效果404页面 3.太空404页面 4.404寻亲页面&#xff08;公益&#xff09; 每一次刷新都是一个公益捐赠活动&#xff01; 以上就是笔者要分享的4个4…

selenium如何打开浏览器,等待用户输入完成后,再运行

selenium如何打开浏览器&#xff0c;等待用户输入完成后&#xff0c;再运行 一、在脚本中&#xff0c;等待用户输入 在使用 Selenium 打开浏览器后等待用户输入完成&#xff0c;可以使用 Python 编写一个简单的脚本来实现。首先&#xff0c;确保你已经安装了 Selenium 和对应的…

selenium浏览器驱动下载

Chrome谷歌浏览器 下载地址&#xff1a;http://chromedriver.storage.googleapis.com/index.html 不同的Chrome的版本对应的chromedriver.exe 版本也不一样&#xff0c;下载时不要搞错了。 如果是最新的Chrome, 下载最新的chromedriver.exe 就可以了。 Firefox火狐浏览器 驱…

点云处理——terrasolid教程

加载terrasolid软件模块 3、通过microstation的utilities->mdl applications加载terrasolid四个模块,加载成功后将显示tscan和tphoto的主窗口&#xff0c;以及四个模块的主工具箱。 浏览点云 4、显示点云坐标信息(类&#xff0c; 航带号&#xff0c;GPS信息&#xff0c;东…

ubuntu 18.04 磁盘太满无法进入系统

安装了一个压缩包&#xff0c;装了一半提示磁盘空间少导致安装失败。我也没在意&#xff0c;退出虚拟机打算扩展硬盘。等我在虚拟机设置中完成扩展操作&#xff0c;准备进入虚拟机内部进行操作时&#xff0c;发现登录不进去了 shift 登入GUN GRUB设置项的问题 网上都是在开机…

Java 版 spring cloud +spring boot 工程系统管理 工程项目管理系统源码 工程项目各模块及其功能点清单

工程项目各模块及其功能点清单 一、系统管理 1、数据字典&#xff1a;实现对数据字典标签的增删改查操作 2、编码管理&#xff1a;实现对系统编码的增删改查操作 3、用户管理&#xff1a;管理和查看用户角色 4、菜单管理&#xff1a;实现对系统菜单的增删改查操…

POLARDB IMCI 白皮书 云原生HTAP 数据库系统 一 数据压缩和打包处理与数据更新

开头还是介绍一下群&#xff0c;如果感兴趣polardb ,mongodb ,mysql ,postgresql ,redis 等有问题&#xff0c;有需求都可以加群群内有各大数据库行业大咖&#xff0c;CTO&#xff0c;可以解决你的问题。加群请联系 liuaustin3 &#xff0c;在新加的朋友会分到2群&#xff08;共…

Qt实现引导界面UITour

介绍 最近做了一款键鼠自动化&#xff0c;想第一次安装打开后搞一个引导界面&#xff0c;找了好多资料没啥参考&#xff0c;偶然发现qt有引导界面如下图。 Qt整挺好&#xff0c;但是未找到源码&#xff0c;真的不想手撸&#xff0c;无奈实在找不到&#xff0c;下图是仿照qt实现…

ALLEGRO之Place

本文主要讲述了ALLEGRO的Place菜单。 &#xff08;1&#xff09;Manually&#xff1a;手动放置&#xff0c;常用元器件放置方法&#xff1b; &#xff08;2&#xff09;Quickplace&#xff1a;快速放置&#xff1b; &#xff08;3&#xff09;Autoplace&#xff1a;自动放置&a…

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

题图来自 Rust vs Go in 2023[1] 221. Remove all non-digits characters Create string t from string s, keeping only digit characters 0, 1, 2, 3, 4, 5, 6, 7, 8, 9. 删除所有非数字字符 package mainimport ( "fmt" "regexp")func main() { s : hei…

【Git】Git GitHub

1. Git1.1 Git基本操作1.2 Git版本回退1.3 Git分支操作 2. Git 配合GitHub2.1 生成密钥2.2 GitHub添加公钥2.3 Git连接GitHub2.4 本地仓库关联远程仓库2.5 本地代码push远程仓库2.6 本地clone远程仓库2.7 本地fetch和pull 1. Git 1.1 Git基本操作 touch test.py 工作区创建文…

[自然语言处理] 自然语言处理库spaCy使用指北

spaCy是一个基于Python编写的开源自然语言处理库。基于自然处理领域的最新研究&#xff0c;spaCy提供了一系列高效且易用的工具&#xff0c;用于文本预处理、文本解析、命名实体识别、词性标注、句法分析和文本分类等任务。 spaCy的官方仓库地址为&#xff1a;spaCy-github。本…

城市气象数据可视化:洞察气候变化,构建智慧城市

随着城市化进程的加速&#xff0c;城市气象数据的采集和分析变得越来越重要。气象数据不仅影响着人们的生活和出行&#xff0c;还与城市的发展和规划息息相关。在数字化时代&#xff0c;如何将城市中各个气象数据进行可视化&#xff0c;让复杂的数据变得简单易懂&#xff0c;成…

VBA技术资料MF35:VBA_在Excel中过滤数据

【分享成果&#xff0c;随喜正能量】好马好在腿&#xff0c;好人好在嘴。不会烧香得罪神&#xff0c;不会讲话得罪人。慢慢的你就会发现&#xff0c;一颗好心&#xff0c;永远比不上一张好嘴。。 我给VBA的定义&#xff1a;VBA是个人小型自动化处理的有效工具。利用好了&#…

MySQL笔记——数据库当中的事务以及Java实现对数据库进行增删改查操作

系列文章目录 MySQL笔记——MySQL数据库介绍以及在Linux里面安装MySQL数据库&#xff0c;对MySQL数据库的简单操作&#xff0c;MySQL的外接应用程序使用说明 MySQL笔记——表的修改查询相关的命令操作 MySQL案例——多表查询以及嵌套查询 文章目录 系列文章目录 前言 一…

Python Web 开发及 Django 总结

title: Python Web 开发及 Django 总结 date: 2023-07-24 17:26:26 tags: PythonWeb categories:Python cover: https://cover.png feature: false Python 基础部分见&#xff1a;Python 基础总结 1. 创建项目 1.1 命令行 1、下载安装 Django 在终端输入 pip install djan…