文章目录
- 1. 设计网页页面
- 1.1 列表页
- 1.2 详情页
- 2. 设计网页的前后端交互接口
- 约定交互1: 获取题目的列表
- 约定交互2: 获取指定题目的详情信息
- 约定交互3: 向服务器提交编写的代码
- 3. 服务器的API
- 3.1 导入 JackSon 库
- 3.2 创建 ProblemServlet 类
- 3.3 测试 ProblemServlet 类
- 3.4 创建 DescServlet 类
- 3.5 测试 DescServlet 类
- 3.6 创建 ResultServlet 类
- 静态内部类 ResultRequest
- 静态内部类 ResultResponse
- 实现 doPost
- 实现 readBody 方法
- 实现 mergeCode 方法
- 3.7 测试 ResultServlet 类
- 3.8 这里发现 如果 id不存在 或者 code为空的时候出现服务器错误.
- 3.9 再次对 ResultServlet 进行测试
1. 设计网页页面
1.1 列表页
只是大概模板
1.2 详情页
只是大概模板
2. 设计网页的前后端交互接口
约定交互1: 获取题目的列表
约定交互2: 获取指定题目的详情信息
约定交互3: 向服务器提交编写的代码
3. 服务器的API
由于这些前后交互需要用到 json 格式去传入数据.(可以不用,但是我这里约定了使用这样的一个格式)
3.1 导入 JackSon 库
3.2 创建 ProblemServlet 类
创建 api 包, 在包下创建 这个类
这个类对应的是交互1
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 是 Jackson 中的一个重要的类private final ObjectMapper objectMapper = new ObjectMapper();@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.setStatus(200);resp.setContentType("application/json;charset=utf8");// 获取全部的题目列表ProblemDao problemDao = new ProblemDao();List<Problem> problems = problemDao.selectAll();// 转化成json格式字符串String respString = objectMapper.writeValueAsString(problems);resp.getWriter().write(respString);}
}
3.3 测试 ProblemServlet 类
3.4 创建 DescServlet 类
同样在api包下, 创建 DescServlet 类
这个类对应交互2
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;@WebServlet("/desc")
public class DescServlet extends HttpServlet {private final ObjectMapper objectMapper = new ObjectMapper();@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.setStatus(200);resp.setContentType("application/json;charset=utf8");// 首先获取到idString idString = req.getParameter("id");if(idString == null || "".equals(idString)){resp.setContentType("text/html;charset=utf-8");resp.getWriter().write("<h3>id丢失</h3>");return;}int id = Integer.parseInt(idString);// 获取对应id题目的详情页ProblemDao problemDao = new ProblemDao();Problem problem = problemDao.selectOne(id);// 将problem 转成json格式字符串 写回响应String respString = objectMapper.writeValueAsString(problem);resp.getWriter().write(respString);}
}
3.5 测试 DescServlet 类
3.6 创建 ResultServlet 类
同样放到 api 包里.
这个类对应的是交互3
由于这里请求也需要带着这个json格式.所以使用两个静态内部类来表示请求body和响应body的格式.
静态内部类 ResultRequest
/*** 结果的请求body格式*/static class ResultRequest{public int id;public String code;}
静态内部类 ResultResponse
/*** 结果的响应body格式*/static class ResultResponse{// error 0:运行成功 1: 编译出错 2: 运行出错 3:其他错误public int error;public String reason;public String stdout;}
实现 doPost
private final ObjectMapper objectMapper = new ObjectMapper();@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.setStatus(200);resp.setContentType("application/json;charset=utf8");// 1. 读取请求正文, 按照json格式读取String body = readBody(req);ResultRequest resultRequest = objectMapper.readValue(body, ResultRequest.class);// 2. 根据 id 从数据库中查找到题目的测试用例ProblemDao problemDao = new ProblemDao();Problem problem = problemDao.selectOne(resultRequest.id);// 测试用例代码String testCode = problem.getTestCode();// 提交的代码String requestCode = resultRequest.code;// 3. 把用户提交的代码和测试用例的代码,给瓶装成一个完整的代码String finalCode = mergeCode(requestCode,testCode);// 4. 创建一个 Task 实例, 调用里面的 compileAndRun 来进行编译运行Task task = new Task();Question question = new Question();question.setCode(finalCode);Answer answer = task.compileAndRun(question);// 5. 根据 Task 运行的结果, 包装成一个 Http 响应ResultResponse resultResponse = new ResultResponse();resultResponse.error = answer.getError();resultResponse.reason = answer.getReason();resultResponse.stdout = answer.getStdout();String respString = objectMapper.writeValueAsString(resultResponse);resp.getWriter().write(respString);}
实现 readBody 方法
/*** 读取请求的正文* @param req 请求* @return 以字符串形式返回* @throws UnsupportedEncodingException 字符编码不支持的异常*/private String readBody(HttpServletRequest req) throws UnsupportedEncodingException {// 1. 根据 Content-Length 获取 body 中的长度(单位是字节)int contentLength = req.getContentLength();// 2. 按照找个长度准备一个 byte[]byte[] buffer = new byte[contentLength];// 3. 通过 req 里面的 getInputStream 方法, 获取body的流对象(body比较长)try (InputStream inputStream = req.getInputStream()){// 4. 基于这个流对象,读取内容,将读取到内容放到byte[]数组中inputStream.read(buffer);} catch (IOException e) {e.printStackTrace();}// 5. 把这个 byte[] 的内容构造成一个 Stringreturn new String(buffer,"utf8");}
实现 mergeCode 方法
/*** 测试用例代码和提交的代码合并* @param requestCode 提交的代码* @param testCode 测试用例代码* @return 返回合并后的代码*/private String mergeCode(String requestCode, String testCode) {// 找到最后一个"}"的位置int index =requestCode.lastIndexOf("}");if (index == -1){// 这里是不存在的情况return null;}// 截取前面的代码String curCode = requestCode.substring(0,index);// 拼接代码return curCode + testCode + "\n}";}
3.7 测试 ResultServlet 类
打开postman应用
如果不会使用postman 可以看 博文 Postman的使用
3.8 这里发现 如果 id不存在 或者 code为空的时候出现服务器错误.
更改代码
并在 comon包中 创建这两个类继承 Exception
当catch到异常的时候, 设置状态码为3
3.9 再次对 ResultServlet 进行测试