0
点赞
收藏
分享

微信扫一扫

在线OJ项目

船长_Kevin 2022-02-21 阅读 32

在线OJ项目

项目简介

核心功能

  • 题目的管理:(题目信息:题干+测试用例)
  • 题目列表页:展示题目列表
  • 题目详情页:展示题目的详细信息+代码编辑框
  • 提交运行题目:点击按钮,网页把源代码交给服务器服务器执行代码,返回是否通过以及测试用例。
  • 查看运行结果:展示上次提交是否通过,错误测试用例,历史提交记录.
  • 登录页:通过用户名密码登录.

实现效果

登录页面
在这里插入图片描述
题目列表页
在这里插入图片描述
题目详情页
在这里插入图片描述

编译模块设计

实现通过命令行调用程序

创建compile包,CommandUtil类
1.掌握标准输入,标准输出,标准错误的概念

  • 标准输入:从标准输入设备(通常为键盘)读取数据,用户输入数据按Enter键输入数据变得可用,read()方法每次返回一个字节的数据.
  • 标准输出:显示器.
  • 标准错误:显示器,显示错误信息.

2实现手动重定向过程,对标准输出,标准错误进行重定向
3.exec执行过程是异步,使用waitFor方法阻塞等待命令执行结束.

public class CommandUtil {
    public static int run(String cmd,String stdoutFile,String stderrFile) {
        try {
            //1.通过Runtime类得到Runtime实例,执行exec方法
            Process process=Runtime.getRuntime().exec(cmd);
            //2.获取到标准输出,并写入到指定文件中
            if(stdoutFile != null) {
                InputStream stdoutFrom = process.getInputStream();
                FileOutputStream stdoutTo = new FileOutputStream(stdoutFile);
                while (true) {
                    int ch=stdoutFrom.read();
                    if(ch == -1) {
                        break;
                    }
                    stdoutTo.write(ch);
                }
                stdoutFrom.close();
                stdoutTo.close();
            }
            //3.获取到标准错误,并写入到指定文件中
            if (stderrFile != null) {
                InputStream stderrFrom = process.getErrorStream();
                FileOutputStream stderrTo = new FileOutputStream(stderrFile);
                while (true) {
                    int ch = stderrFrom.read();
                    if(ch == -1) {
                        break;
                    }
                    stderrTo.write(ch);
                }
                stderrFrom.close();
                stderrTo.close();
            }
            //4.等待子进程结束,拿到子进程的状态码,并返回
           int exitCode=process.waitFor();
            return exitCode;
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
        return 1;
    }
  }

验证CommandUtil类

public static void main(String[] args) {
        CommandUtil.run("javac","stdout.txt","stderr.txt");
    }

实现编译运行过程

在compile包下,创建以下类:

创建Question类

Question类,代表输入的代码.

public class Question {
    private String code;

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }
}

创建Answer类

Answer类代表输出内容,Answer类中包含错误码,错误提示,运行程序得到的标准输出,运行程序得到的标准错误。

public class Answer {
    //错误码,约定error为0表示编译运行都ok,为1表示编译出错,为2表示运行出错
    private int error;
    //出错的提示信息 如果error为1编译出错,reason中放编译错误信息,为2运行异常,reason放异常错误信息
    private String reason;
    //运行程序得到的标准输出
    private String stdout;
    //运行程序得到的标准错误
    private String stderr;

    public int getError() {
        return error;
    }

    public void setError(int error) {
        this.error = error;
    }

    public String getReason() {
        return reason;
    }

    public void setReason(String reason) {
        this.reason = reason;
    }

    public String getStdout() {
        return stdout;
    }

    public void setStdout(String stdout) {
        this.stdout = stdout;
    }

    public String getStderr() {
        return stderr;
    }

    public void setStderr(String stderr) {
        this.stderr = stderr;
    }

    @Override
    public String toString() {
        return "Answer{" +
                "error=" + error +
                ", reason='" + reason + '\'' +
                ", stdout='" + stdout + '\'' +
                ", stderr='" + stderr + '\'' +
                '}';
    }
}

创建Task类

Task类,每一次的编译运行称为一个Task。

public class Task {
      public Answer compileAndRun(Question question) {
      //1.创建用来存放临时文件的目录
      //2.根据Question创建临时文件
      //3.构造编译命令并执行
      //4.构建运行命令并执行
      //5.将运行结果打包到最终的Answer对象中
     }
}

约定临时文件名

为了有效进行”进程间的通信”,首先我们使用一组常量来约束临时文件的名字。

//临时文件所在目录
    private static final String WORK_DIR="./tmp/";
    //约定代码类名
    private static final String CLASS="Solution";
    //约定要编译的代码文件名
    private static final String CODE=WORK_DIR+"Solution.java";
    //约定存放编译错误信息的文件名
    private static final String COMPILE_ERROR=WORK_DIR+"compileError.txt";
    //约定存放运行时标准输出的文件名
    private static final String STDOUT=WORK_DIR+"stdout.txt";
    //约定存放运行时标准错误的文件名
    private static final String STDERR=WORK_DIR+"stderr.txt";

创建FileUtil类

创建common包,创建FileUtil类进行文件的读写操作.
为了方便后面的文件操作,先进行简单封装.
创建common包,创建FileUtil类

public class FileUtil {
    //负责把filePath对应的文件内容读出来,放到返回值中
    public static String readFile(String filePath) {
        StringBuilder result=new StringBuilder();
       try(FileReader fileReader=new FileReader(filePath)) {
          while (true) {
              int ch= fileReader.read();
              if(ch==-1) {
                  break;
              }
              result.append((char)ch);
          }

       } catch (IOException e) {
           e.printStackTrace();
       }
       return result.toString();

    }
    //负责把content写入到filePath对应的文件中
    public static void writeFile(String filePath,String content) {
        try(FileWriter fileWriter=new FileWriter(filePath)) {
            fileWriter.write(content);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
 }

实现Task.compileAndRun方法

使用compileAndRun方法封装编译命令,并得到编译结果.
complieAndRun方向实现步骤

  1. 创建用来存放临时文件的目录。
  2. 把question中的内容写到指定的Solution.java文件中。
  3. 创建子进程调用javac命令进行编译。
  4. 创建子进程调用java命令并执行。
  5. 父进程获取到编译执行结果,打包成Answer对象。
public class Task {
    //参数:要编译运行的java源代码
    //返回值:表示编译运行的结果:编译出错/运行出错/运行正确
    public Answer compileAndRun(Question question) {
        Answer answer=new Answer();
        //0.创建用来存放临时文件的目录
        File workDir=new File(WORK_DIR);
        if(!workDir.exists()) {
            //创建多级目录
            workDir.mkdirs();
        }
        //1.把question中的code写入到一个Solution.java文件中
        FileUtil.writeFile(CODE,question.getCode());
        //2.创建子进程,调用javac进行编译
        //先构造编译命令
        String compileCmd=String.format("javac -encoding utf8 %s -d %s",CODE,WORK_DIR);
        //对应javac进程来说,标准输出不关注,关注标准错误,一旦编译出错内容就会通过标准错误来反馈
        CommandUtil.run(compileCmd,null,COMPILE_ERROR);
        //如果编译出错,错误信息就会放到COMPILE_ERROR这个文件中,没有出错文件为空
        String compileError=FileUtil.readFile(COMPILE_ERROR);
        if(!compileError.equals("")) {
            //编译错误 直接返回Answer 约定1表示编译出错
            System.out.println("编译出错");
            answer.setError(1);
            answer.setReason(compileError);
            return answer;
        }

        //3.创建子进程,调用java命令并执行
        String runCom = String.format("java -classpath %s %s",WORK_DIR,CLASS);
        CommandUtil.run(runCom,STDOUT,STDERR);
        String runError=FileUtil.readFile(STDERR);
        if(!runError.equals("")) {
            System.out.println("运行出错");
            answer.setError(2);
            answer.setReason(runError);
            return answer;
        }
        //4.父进程获取到刚才的编译执行的结果,并打包成Answer对象
        answer.setError(0);
        answer.setStdout(FileUtil.readFile(STDOUT));
        return answer;
    }
}

验证Task类

public static void main(String[] args) {
        Task task=new Task();
        Question question=new Question();
        question.setCode("public class Solution {\n" +
                "    public static void main(String[] args) {\n" +
                "        System.out.println(\"hello world\");\n" +
                "    }\n" +
                "    \n" +
                "}");
        Answer answer=task.compileAndRun(question);
        System.out.println(answer);
    }

题目管理模块设计

数据库设计

create database if not exists oj_databases;
use oj_databases;

drop table if exists oj_table;
create table oj_table(
     id int primary key auto_increment,
     title varchar(50),
     level varchar(20),
     description varchar(4096),
     templateCode varchar(4096),
     testCode varchar(4096)
);

drop table if exists user;
create table user(
    userId int primary key auto_increment,
    username varchar(128),
    password varchar(128)
);

title表示题目标题,level表示难度,description表示题目描述,templateCode表示代码模板,testCode表示测试用例代码.

创建DBUtil类

在common包下创建DBUtil类.
完成数据库连接操作.

public class DBUtil {
    private static final String url="jdbc:mysql:///oj_databases?useUnicode=true&characterEncoding=UTF8&serverTimezone=UTC&useSSL=false";
    private static final String USERNAME="root";
    private static final String PASSWORD="1234";

    private static volatile DataSource dataSource=null;
    //实现getDataSource,线程安全单例模式
    public static DataSource getDataSource() {
        if(dataSource==null) {
            synchronized (DBUtil.class) {
                if(dataSource==null) {
                    dataSource=new MysqlDataSource();
                    ((MysqlDataSource)dataSource).setURL(url);
                    ((MysqlDataSource)dataSource).setUser(USERNAME);
                    ((MysqlDataSource)dataSource).setPassword(PASSWORD);
                }
            }
        }
        return dataSource;
    }
    //实现getConnection
    public static Connection getConnection() throws SQLException {
        return getDataSource().getConnection();
    }
    //实现close
    public static void close(Connection connection, PreparedStatement statement, ResultSet resultSet){
        if(resultSet!=null) {
            try {
                resultSet.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(statement!=null) {
            try {
                statement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(connection!=null) {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

    }
}

实现题目存储用户存储

创建dao包,以下类都在dao包下创建.

创建Problem类

Problem类表示一道题目。

public class Problem {
    private  int id;
    private  String title;
    private  String level;
    private  String description;
    private  String templateCode;
    private  String testCode;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getLevel() {
        return level;
    }

    public void setLevel(String level) {
        this.level = level;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public String getTemplateCode() {
        return templateCode;
    }

    public void setTemplateCode(String templateCode) {
        this.templateCode = templateCode;
    }

    public String getTestCode() {
        return testCode;
    }

    public void setTestCode(String testCode) {
        this.testCode = testCode;
    }

    @Override
    public String toString() {
        return "Problem{" +
                "id=" + id +
                ", title='" + title + '\'' +
                ", level='" + level + '\'' +
                ", description='" + description + '\'' +
                ", templateCode='" + templateCode + '\'' +
                ", testCode='" + testCode + '\'' +
                '}';
    }
}

创建ProblemDao类

题目管理器类,负责和数据库交互.

public class ProblemDAO {
// 新增题目
    public void insert(Problem problem) {
        // TODO
    }

    // 删除题目
    public void delete(int id) {
        // TODO
    }
    // 查询所有题目
    public List<Problem> selectAll() {

    }

    // 查询指定题目详情
    public Problem selectOne(int problemId) {

    }
}

实现insert

public void insert(Problem problem) {
        Connection connection=null;
        PreparedStatement statement=null;
        try {
            connection=DBUtil.getConnection();
            String sql="insert into oj_table values(null,?,?,?,?,?)";
            statement=connection.prepareStatement(sql);
            statement.setString(1,problem.getTitle());
            statement.setString(2,problem.getLevel());
            statement.setString(3,problem.getDescription());
            statement.setString(4,problem.getTemplateCode());
            statement.setString(5,problem.getTestCode());
            int ret=statement.executeUpdate();
            if(ret!=1) {
                System.out.println("新增题目失败");
            } else {
                System.out.println("新增题目成功");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtil.close(connection,statement,null);
        }
    }

实现delete

 public void delete(int id) {
        Connection connection=null;
        PreparedStatement statement=null;
        try {
            connection=DBUtil.getConnection();
            String sql="delete from oj_table where id=?";
            statement=connection.prepareStatement(sql);
            statement.setInt(1,id);
            int ret=statement.executeUpdate();
            if(ret!=1) {
                System.out.println("删除题目失败");
            } else {
                System.out.println("删除题目成功");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtil.close(connection,statement,null);
        }
    }

实现selectAll

public List<Problem> selectAll() {
        List<Problem> list=new ArrayList<>();
        Connection connection=null;
        PreparedStatement statement=null;
        ResultSet resultSet=null;
        try {
            connection=DBUtil.getConnection();
            String sql="select * from oj_table";
            statement=connection.prepareStatement(sql);
            resultSet=statement.executeQuery();
            while (resultSet.next()) {
                Problem problem=new Problem();
                problem.setId(resultSet.getInt("id"));
                problem.setTitle(resultSet.getString("title"));
                problem.setLevel(resultSet.getString("level"));
                list.add(problem);
            }
            return list;
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtil.close(connection,statement,resultSet);
        }
        return null;
    }

实现selectOne

 public Problem selectOne(int id) {
        Problem problem=new Problem();
        Connection connection=null;
        PreparedStatement statement=null;
        ResultSet resultSet=null;
        try {
            connection=DBUtil.getConnection();
            String sql="select * from oj_table where id=?";
            statement=connection.prepareStatement(sql);
            statement.setInt(1,id);
            resultSet=statement.executeQuery();
            if(resultSet.next()) {
                problem.setId(resultSet.getInt("id"));
                problem.setTitle(resultSet.getString("title"));
                problem.setLevel(resultSet.getString("level"));
                problem.setDescription(resultSet.getString("description"));
                problem.setTemplateCode(resultSet.getString("templateCode"));
                return problem;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtil.close(connection,statement,resultSet);
        }
        return null;
    }

验证insert

private static void testInsert() {
        ProblemDao problemDAO=new ProblemDao();
        Problem problem=new Problem();
        problem.setTitle("两数之和");
        problem.setLevel("简单");
        problem.setDescription("给定一个整数数组 nums和一个整数目标值 target,请你在该数组中找出 和为目标值 target的那两个整数,并返回它们的数组下标。\n" +
                "\n" +
                "你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。\n" +
                "\n" +
                "你可以按任意顺序返回答案。\n" +
                "\n" +
                "\n" +
                "\n" +
                "示例 1:\n" +
                "\n" +
                "输入:nums = [2,7,11,15], target = 9\n" +
                "输出:[0,1]\n" +
                "解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。\n" +
                "示例 2:\n" +
                "\n" +
                "输入:nums = [3,2,4], target = 6\n" +
                "输出:[1,2]\n" +
                "示例 3:\n" +
                "\n" +
                "输入:nums = [3,3], target = 6\n" +
                "输出:[0,1]\n" +
                "\n" +
                "\n" +
                "提示:\n" +
                "\n" +
                "2 <= nums.length <= 104\n" +
                "-109 <= nums[i] <= 109\n" +
                "-109 <= target <= 109\n" +
                "只会存在一个有效答案\n" +
                "\n" );
        problem.setTemplateCode("class Solution {\n" +
                "    public int[] twoSum(int[] nums, int target) {\n" +
                "\n" +
                "    }\n" +
                "}");
        problem.setTestCode("public static void main(String[] args) {\n" +
                "        Solution solution=new Solution();\n" +
                "        //testcase1\n" +
                "        int[] nums={2,7,11,15};\n" +
                "        int target=9;\n" +
                "        int[] result=solution.twoSum(nums,target);\n" +
                "        if(result.length==2 &&result[0]==0&&result[1]==1) {\n" +
                "            System.out.println(\"testcase1 Ok\");\n" +
                "        } else {\n" +
                "            System.out.println(\"testcase1 failed\");\n" +
                "        }\n" +
                "        //testcase2\n" +
                "        int[] nums2={3,2,4};\n" +
                "        int target2=6;\n" +
                "        int[] result2=solution.twoSum(nums2,target2);\n" +
                "        if(result.length==2 &&result2[0]==1&&result2[1]==2) {\n" +
                "            System.out.println(\"testcase2 Ok\");\n" +
                "        } else {\n" +
                "            System.out.println(\"testcase2 failed\");\n" +
                "        }\n" +
                "    }");
        problemDAO.insert(problem);
    }

验证delete

 public static void testDelete() {
        ProblemDao problemDao=new ProblemDao();
        problemDao.delete(5);
    }

验证selectAll

public static void testSelectAll() {
        ProblemDao problemDao=new ProblemDao();
        List<Problem> problems=problemDao.selectAll();
        System.out.println(problems);
    }

验证selectOne

public static void testSelectOne() {
        ProblemDao problemDao=new ProblemDao();
        Problem problem=problemDao.selectOne(7);
        System.out.println(problem);
    }

创建User类

表示一个用户,用户Id,用户名,密码.

public class User {
    private int userId;
    private String username;
    private String password;

    public int getUserId() {
        return userId;
    }

    public void setUserId(int userId) {
        this.userId = userId;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "User{" +
                "userId=" + userId +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

创建UserDao类

用户管理器类,负责和数据库交互.

public class UserDao {
    //新增用户
    public void insert(User user) {
    }
    //删除用户
    public void delete(int userId) {
    }
    //根据用户名查询用户
    public User select(String username) {
    }
    //根据用户id查询用户
    public User selectId(int userId) {
    }
}    

实现insert

public void insert(User user) {
        Connection connection=null;
        PreparedStatement statement=null;
        try {
            connection= DBUtil.getConnection();
            String sql="insert into user values(null,?,?)";
            statement=connection.prepareStatement(sql);
            statement.setString(1,user.getUsername());
            statement.setString(2,user.getPassword());
            int ret=statement.executeUpdate();
            if(ret!=1) {
                System.out.println("新增用户失败");
            } else {
                System.out.println("新增用户成功");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtil.close(connection,statement,null);
        }
    }

实现delete

public void delete(int userId) {
        Connection connection=null;
        PreparedStatement statement=null;
        try {
            connection=DBUtil.getConnection();
            String sql="delete  from user where userId=?";
            statement=connection.prepareStatement(sql);
            statement.setInt(1,userId);
            int ret=statement.executeUpdate();
            if(ret!=1) {
                System.out.println("删除用户失败");
            } else {
                System.out.println("删除用户成功");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtil.close(connection,statement,null);
        }
    }

实现select

 public User select(String username) {
        User user=new User();
        Connection connection=null;
        PreparedStatement statement=null;
        ResultSet resultSet=null;
        try {
            connection=DBUtil.getConnection();
            String sql="select * from user where username=?";
            statement=connection.prepareStatement(sql);
            statement.setString(1,username);
            resultSet=statement.executeQuery();
            if(resultSet.next()) {
                user.setUserId(resultSet.getInt("userId"));
                user.setUsername(resultSet.getString("username"));
                user.setPassword(resultSet.getString("password"));
                return user;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtil.close(connection,statement,resultSet);
        }
        return null;
    }

实现selectId

public User selectId(int userId) {
        User user=new User();
        Connection connection=null;
        PreparedStatement statement=null;
        ResultSet resultSet=null;
        try {
            connection=DBUtil.getConnection();
            String sql="select * from user where userId=?";
            statement=connection.prepareStatement(sql);
            statement.setInt(1,userId);
            resultSet=statement.executeQuery();
            if(resultSet.next()) {
                user.setUserId(resultSet.getInt("userId"));
                user.setUsername(resultSet.getString("username"));
                user.setPassword(resultSet.getString("password"));
                return user;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtil.close(connection,statement,resultSet);
        }
        return null;
    }

验证insert

private static void testInsert() {
        UserDao userDao=new UserDao();
        User user=new User();
        user.setUsername("zhangsan");
        user.setPassword("1234");
        userDao.insert(user);
    }

验证delete

private static void testDelete(int id) {
        UserDao userDao=new UserDao();
        userDao.delete(id);
    }

验证select

 private static void testSelect(String name) {
        UserDao userDao=new UserDao();
        User user=userDao.select(name);
        System.out.println(user);
    }

验证selectId

private static void testSelectId(int Id) {
        UserDao userDao=new UserDao();
        User user=userDao.selectId(Id);
        System.out.println(user);
    }

服务器API

创建API包,以下类都在API包中

实现ProblemServlet类

根据req中是否包含id来确定是获取题目列表页还是获取题目详情页,有id获取题目详情页,无id获取题目列表页.

@WebServlet("/problem")
public class ProblemServlet extends HttpServlet {
    private ObjectMapper objectMapper=new ObjectMapper();

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setStatus(200);
        resp.setContentType("application/json;charset=utf8");
        ProblemDao problemDao=new ProblemDao();
        String idString=req.getParameter("id");
        if(idString==null||idString.equals("")) {
            //获取题目列表页
            List<Problem> list=problemDao.selectAll();
            String respString=objectMapper.writeValueAsString(list);
            resp.getWriter().write(respString);
        } else {
            //获取题目详情页
            Problem problem=problemDao.selectOne(Integer.parseInt(idString));
            String respString=objectMapper.writeValueAsString(problem);
            resp.getWriter().write(respString);
        }
    }
}

实现CompileServlet

其中包含两个内部类,分别对应编译请求和编译响应.

@WebServlet("/compile")
public class CompileServlet extends HttpServlet {
    static class CompileRequest {
        public int id;
        public String code;
    }
    static class CompileResponse {
        public int error;
        public String reason;
        public String stdout;
    }
    private ObjectMapper objectMapper=new ObjectMapper();
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    //1.读取请求并按照json格式解析
    //2.根据请求中的id找到对应题目的详情
    //3.将用户提交代码和测试用例进行拼接
     //4.创建Task类编译运行代码
    }
}

实现doPost方法

 @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        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) {
                //找不到对应的题目id
                throw new ProblemNotFoundExec();
            }
            //用户提交的代码
            String requestCode=compileRequest.code;
            //测试用例
            String testCode=problem.getTestCode();
            //3.将用户提交代码和测试用例进行拼接
            String finalCode=mergeCode(requestCode,testCode);
            if(finalCode==null) {
                throw new CodeInValidException();
            }
            //4.创建Task类编译运行代码
            Task task=new Task();
            Question question=new Question();
            question.setCode(finalCode);
            Answer answer=task.compileAndRun(question);
            compileResponse.error=answer.getError();
            compileResponse.reason=answer.getReason();
            compileResponse.stdout=answer.getStdout();
        } catch (ProblemNotFoundExec problemNotFoundExec) {
            compileResponse.error=3;
            compileResponse.reason="题目id不存在id="+compileRequest.id;
        } catch (CodeInValidException e) {
            compileResponse.error=3;
            compileResponse.reason="提交代码不合格";
        } finally {
            String respString=objectMapper.writeValueAsString(compileResponse);
            resp.getWriter().write(respString);
        }
    }

实现readBody方法,把请求中的body全部读出来.

private static String readBody(HttpServletRequest req) throws UnsupportedEncodingException {
        int len=req.getContentLength();
        byte[] bytes=new byte[len];
        try(InputStream inputStream=req.getInputStream()) {
            inputStream.read(bytes);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return new String(bytes,"utf8");
    }

实现mergeCode方法,将用户提交的代码和测试用例进行拼接.

 private String mergeCode(String requestCode, String testCode) {
        int index=requestCode.lastIndexOf("}");
        if(index==-1) {
            return null;
        }
        String subStr=requestCode.substring(0,index);
        return subStr+testCode+"\n}";
    }

实现LoginServlet

通过from表单进行前后端交互.

@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("test/html,charset=utf8");
        req.setCharacterEncoding("utf8");
        String username=req.getParameter("username");
        String password=req.getParameter("password");
        if(username==null||password==null||username.equals("")||password.equals("")) {
            String html="<h3>登录失败!用户名或密码错误<h3>";
            resp.getWriter().write(html);
            return;
        }
        UserDao userDao=new UserDao();
        User user=userDao.select(username);
        if(user==null) {
            String html="<h3>登录失败!用户名或密码错误<h3>";
            resp.getWriter().write(html);
            return;
        }
        if(!user.getPassword().equals(password)) {
            String html="<h3>登录失败!用户名或密码错误<h3>";
            resp.getWriter().write(html);
            return;
        }
       HttpSession session=req.getSession(true);
        session.setAttribute("username",username);
        resp.sendRedirect("index.html");
    }
}

举报

相关推荐

0 条评论