精华内容
下载资源
问答
  • 今天小编就为大家分享一篇Java实现OJ多组测试数据的输入方法,具有很的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
  • java怎么做oj

    2021-02-12 09:37:16
    示例代码 :public static void main(String[] args) {System.out.println("Start...");ExecutorService exec = Executors.newCachedThreadPool();testTask(exec, 15); //任务成功结束后等待计算结果,不需要等到15...

    示例代码 :public static void main(String[] args) {

    System.out.println("Start...");

    ExecutorService exec = Executors.newCachedThreadPool();

    testTask(exec, 15); //任务成功结束后等待计算结果,不需要等到15秒

    testTask(exec, 5); //只等待5秒,任务还没结束,所以将任务中止

    exec.shutdown();

    System.out.println("End!");

    }

    private static void testTask(ExecutorService exec, int timeout) {

    MyTask task = new MyTask();

    Future future = exec.submit(task);

    Boolean taskResult = null;

    String failReason = null;

    try {

    //等待计算结果,最长等待timeout秒,timeout秒后中止任务

    taskResult = future.get(timeout, TimeUnit.SECONDS);

    } catch (InterruptedException e) {

    failReason = "主线程在等待计算结果时被中断!";

    } catch (ExecutionException e) {

    failReason = "主线程等待计算结果,但计算抛出异常!";

    } catch (TimeoutException e) {

    failReason = "主线程等待计算结果超时,因此中断任务线程!";

    exec.shutdownNow();

    }

    System.out.println("\ntaskResult : " + taskResult);

    System.out.println("failReason : " + failReason);

    }

    2013年4月01日 10:34

    展开全文
  • 北邮大三javaoj必要哦,当初oj可是是个严谨的老师呢
  • java hustoj forked from Introduction 简介 HUSTOJ is an GPL FreeSoftware?. HUSTOJ 是采用GPL的自由软件。 因googlecode受阻,最新更新迁移至此。 注意:基于本项目源码从事科研、论文、系统开发,必须在文中或...
  • 基于Java开发的在线OJ项目

    千次阅读 多人点赞 2020-10-25 15:16:07
    巩固JDBC、Http、Servlet和Java基础等内容 实现一个在线做题、判题系统 1.2 项目平台与技术栈 技术栈:Servlet、Mysql、Runtime 平台与环境:Windows、IDEA、Maven、Tomcat 1.3 项目功能 进入题目列表页,展示...

    一、项目说明

    1.1 项目目标

    • 巩固JDBC、Http、Servlet和Java基础等内容
    • 实现一个在线做题、判题系统

    1.2 项目平台与技术栈

    • 技术栈:Servlet、Mysql、Runtime
    • 平台与环境:Windows、IDEA、Maven、Tomcat

    1.3 项目功能

    • 进入题目列表页,展示当前系统中的所有题目
    • 进入题目详情页,展示题目的具体要求和代码模块,提供一个编辑框来供用户编辑
    • 对Java代码的编译/运行/测试功能,针对用户提交的代码进行编译运行,并自动执行测试用例、返回测试结果

    二、项目演示

    2.1 进入题目列表页

    在这里插入图片描述

    2.2 进入题目详情页

    在这里插入图片描述

    2.3 编写代码

    在这里插入图片描述

    2.4 提交运行

    点击提交之后,服务器最终会将结果会返给客户端。

    在这里插入图片描述

    三、系统流程(核心)

    起初,我们需要在后台录入题目和测试用例。

    四、系统设计

    4.1 执行指令设计

    通过Runtime对象下的exec()方法能让Java代码去执行一个具体的指令,并且将标准输出和标准错误进行重定向。

    4.2 编译和运行设计

    • 一次编译过程中依赖要编译的代码,和标准输入中的内容
    • 一次编译运行过程中会产生:状态码、出错原因、标准输出对应的内容、标准错误对应的内容
    • 编译过程中依赖临时文件:要编译运行的文件、编译错误对应的文件、标准输出对应的文件、标准错误对应的文件

    4.3 读写文件的设计

    • 将指定文件中的内容读到String中
    • 将String中的内容写到指定文件中

    4.4 数据库设计

    需要保存题目id、标题、难易程度、描述信息、模板代码和测试用例

    4.5 JDBC工具类

    • 获取数据库连接
    • 释放资源

    4.6 题目增删查的设计

    4.6.1 查

    用sql语句直接去数据库中查询

    • 获取题目列表
      • 获取所有题目id、标题、难易程度
    • 获取一道题目详细信息
      • 获取指定id题目的id、标题、难易程度、描述信息、模板代码、测试用例;测试用例不提供给客户端。

    4.6.2 增

    插入题目的id、标题、难易程度、描述信息、模板代码、测试用例信息到数据库中

    4.6.3 删

    删除数据库中指定id的行

    4.7 题目信息API

    4.7.1 获取题目列表页

    系统流程橘色部分对应模块

    4.7.2 获取题目详情页

    系统流程黄色部分对应模块

    4.8 提交运行API

    系统流程绿色部分对应模块

    4.9 前端设计

    五、开发步骤

    5.1 创建maven项目

    在pom.xml文件中引入依赖包

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>haozhang</groupId>
        <artifactId>online_oj</artifactId>
        <version>1.0-SNAPSHOT</version>
        <packaging>war</packaging>
    
        <!-- <name>blogdemo Maven Webapp</name> -->
        <!-- FIXME change it to the project's website -->
        <!-- <url>http://www.example.com</url> -->
    
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <maven.compiler.source>1.8</maven.compiler.source>
            <maven.compiler.target>1.8</maven.compiler.target>
        </properties>
    
        <dependencies>
    
            <!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
            <dependency>
                <groupId>com.google.code.gson</groupId>
                <artifactId>gson</artifactId>
                <version>2.8.5</version>
            </dependency>
    
    
            <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
            <dependency>
                <groupId>javax.servlet</groupId>
                <!--    servlet和tomcat版本有对应关系        -->
                <artifactId>javax.servlet-api</artifactId>
                <version>3.1.0</version>
                <!--这个意思是我们只在开发阶段使用servlet,部署到tomcat上的时候就不需要了-->
                <scope>provided</scope>
            </dependency>
    
            <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.49</version>
            </dependency>
    
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.11</version>
                <scope>test</scope>
            </dependency>
        </dependencies>
    
        <build>
            <finalName>online_oj</finalName>
            <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
                <plugins>
                    <plugin>
                        <artifactId>maven-clean-plugin</artifactId>
                        <version>3.1.0</version>
                    </plugin>
                    <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
                    <plugin>
                        <artifactId>maven-resources-plugin</artifactId>
                        <version>3.0.2</version>
                    </plugin>
                    <plugin>
                        <artifactId>maven-compiler-plugin</artifactId>
                        <version>3.8.0</version>
                    </plugin>
                    <plugin>
                        <artifactId>maven-surefire-plugin</artifactId>
                        <version>2.22.1</version>
                    </plugin>
                    <plugin>
                        <artifactId>maven-war-plugin</artifactId>
                        <version>3.2.2</version>
                    </plugin>
                    <plugin>
                        <artifactId>maven-install-plugin</artifactId>
                        <version>2.5.2</version>
                    </plugin>
                    <plugin>
                        <artifactId>maven-deploy-plugin</artifactId>
                        <version>2.8.2</version>
                    </plugin>
                </plugins>
            </pluginManagement>
        </build>
    </project>
    

    5.2 编译模块设计

    5.2.1 设计类让Java代码可以执行一条指令

    package compile;
    
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    
    /**
     * 
     * 借助这个类让Java代码能够去执行一个具体的命令
     * 如 javac Test.java
     *
     * @author haozhang
     * @date 2020/09/04
     */
    public class CommandUtil {
    
        /**
         *
         * @param cmd 要执行的命令
         * @param stdoutFile 表示标准输出结果重定向到那个文件中  如果为null表示不需要重定向
         * @param stderrFile 表示标准错误结果重定向到哪个文件中
         * @throws IOException
         */
        public static int run(String cmd, String stdoutFile, String stderrFile) throws IOException, InterruptedException {
            //1.获取Runtime对象,Runtime对象是一个单例的
            Runtime runtime = Runtime.getRuntime();
    
            //2.通过Runtime中的 exec 方法来执行一个指令 相当于在命令行中执行cmd命令
            Process process = runtime.exec(cmd);
    
            //3.针对标准输出进行重定向
            if (stdoutFile != null) {
                InputStream stdoutFrom = process.getInputStream();
                OutputStream stdoutTo = new FileOutputStream(stdoutFile);
    
                int ch = -1;
                while ((ch = stdoutFrom.read()) != -1) {
                    stdoutTo.write(ch);
                }
    
                stdoutFrom.close();
                stdoutTo.close();
            }
    
            //4.针对标准错误重定向
            if (stderrFile != null) {
                InputStream stderrFrom = process.getErrorStream();
                OutputStream stderrTo = new FileOutputStream(stderrFile);
    
                int ch = -1;
                while ((ch = stderrFrom.read()) != -1) {
                    stderrTo.write(ch);
                }
    
                stderrFrom.close();
                stderrTo.close();
            }
    
            //5.为了确保子进程先执行完  就需要加上进程等待的逻辑
            //父进程会在这里阻塞,直到子进程执行结束,才继续往下执行
            int exitCode = process.waitFor();
            return exitCode;
    
        }
    
        public static void main(String[] args) throws IOException, InterruptedException {
            run("javac", "d:/oj/stdout.txt", "d:/oj/stderr.txt");
        }
    }
    

    5.2.2 一次编译过程中的依赖

    package compile;
    
    /**
     * 
     * 一次编译运行过程中都依赖哪写数据
     *
     * @author haozhang
     * @date 2020/09/04
     */
    public class Question {
        /**
         * 要编译和执行的代码
         */
        private String code;
    
        /**
         * 执行时标准输入要输入的内容
         *    我们实际上没用
         */
        private String stdin;
    
        public String getCode() {
            return code;
        }
    
        public void setCode(String code) {
            this.code = code;
        }
    
        public String getStdin() {
            return stdin;
        }
    
        public void setStdin(String stdin) {
            this.stdin = stdin;
        }
    }
    

    5.2.3 一次编译运行过程中产生的数据

    package compile;
    
    /**
     * 一次编译运行过程中都产生了哪写数据
     *
     * @author haozhang
     * @date 2020/09/04
     */
    public class Answer {
    
        /**
         * 通过error来表示当前的错误类型
         * 0 表示没错
         * 1 表示编译出错
         * 2 表示运行出错
         */
        private int error;
    
        /**
         * 表示具体的出错原因。可能是编译错误,也可能是运行错误(异常信息)
         */
        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 + '\'' +
                    '}';
        }
    }
    
    

    5.2.4 描述一次编译运行的过程

    package compile;
    
    import common.FileUtil;
    
    import java.io.File;
    import java.io.IOException;
    
    /**
     * 借助这个类来描述一次编译运行的过程
     *
     * @author haozhang
     * @date 2020/09/04
     */
    public class Task {
    
        /**
         * 编译过程中依赖了一些临时文件,需要约定临时文件名称
         *
         * 这些临时文件就是为了把编译执行过程中涉及到的各种中间结果记录下来
         */
    
        /**
         * 所有临时文件都放在 tmp 中
         */
        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 STDIN = WORK_DIR + "stdin.txt";
    
        /**
         *标准输出对应的文件(编译执行的代码结果放到这个文件中)
         */
        private static final String STDOUT = WORK_DIR + "stdout.txt";
    
        /**
         * 标准错误对应的文件(编译执行的代码结果放到这个文件中)
         */
        private static final String STDERR = WORK_DIR + "stderr.txt";
    
        /**
         * 编译错误对应的文件(编译出错时的具体原因)
         */
        private static final String COMPILE_ERROR = WORK_DIR + "compile_error.txt";
    
        public Answer compileAndRun(Question question) throws IOException, InterruptedException {
            Answer answer = new Answer();
            //0.先创建好存放临时文件的目录
            File wordDir = new File(WORK_DIR);
            if (!wordDir.exists()) {
                wordDir.mkdirs();
            }
            //1.根据question去构造一些需要的临时文件
            FileUtil.writeFile(CODE, question.getCode());
            FileUtil.writeFile(STDIN, question.getStdin());
            //2.构造编译命令并执行
                //2.1 形如  javac -encoding UTF-8 ./tmp/Solution.java -d ./tmp/
            String cmd = String.format(
                    "javac -encoding UTF-8 %s -d %s", CODE, WORK_DIR
            );
            System.out.println("编译命令:" + cmd);
            CommandUtil.run(cmd, null, COMPILE_ERROR);
                //2.2编译完成之后,判读编译是否出错,如果出错就不需要再执行
                //认为 COMPILE_ERROR 文件为空表示编译未出错,非空表示编译出错
            String compileError = FileUtil.readFile(COMPILE_ERROR);
            if (!"".equals(compileError)) {
                System.out.println("编译出错");
                answer.setError(1);
                answer.setReason(compileError);
                return answer;
            }
            //3.构造运行命令并执行  形如 java -classpath /.tmp/ Solution
            //为了能让Java命令正确找到类对应的.class文件,需要指定加载路径。-classpath 选项来指定
            cmd = String.format(
                "java -classpath %s %s", WORK_DIR, CLASS
            );
            System.out.println("运行命令:" + cmd);
            CommandUtil.run(cmd, STDOUT, STDERR);
            //判断运行是否出错   查看STDERR 是否为空
            String stdErr = FileUtil.readFile(STDERR);
            if (!"".equals(stdErr)) {
                System.out.println("运行出错");
                answer.setError(2);
                answer.setReason(stdErr);
                return answer;
            }
            //4.将运行结果包装到Answer对象中
            answer.setError(0);
            answer.setStdout(FileUtil.readFile(STDOUT));
            return answer;
        }
    
        public static void main(String[] args) throws IOException, InterruptedException {
            Question question = new Question();
            question.setCode(
                    "public class Solution {\n" +
                            " public static void main(String[] args) {\n" +
                                "String s = null;\n" +
                                "System.out.println(s.length());\n" +
                            "}\n" +
                    "}\n"
            );
            question.setStdin("");
            Task task = new Task();
            Answer answer = task.compileAndRun(question);
            System.out.println(answer);
        }
    }
    
    

    5.3 数据库设计

    package common;
    
    import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
    
    import java.sql.Connection;
    import javax.sql.DataSource;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    /**
     * 6、
     * 和数据库建立连接,进一步操作数据库
     *
     * @author haozhang
     * @date 2020/09/04
     */
    public class DBUtil {
        private static final String URL = "jdbc:mysql://127.0.0.1:3306/online_oj?characterEncoding=utf8&useSSL=true";
    
        private static final String USERNAME = "root";
    
        private static final String PASSWORD = "";
        
        private static DataSource dataSource = null;
    
        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;
        }
    
        public static Connection getConnection() {
            try {
                //内置了数据库连接池
                return getDataSource().getConnection();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return null;
        }
    
        public static void close(Connection connection, PreparedStatement statement, ResultSet result) {
            try {
                if (result != null) {
                    result.close();
                }
    
                if (statement != null) {
                    statement.close();
                }
    
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    
    

    读写文件类设计

    package common;
    
    import java.io.*;
    
    /**
     * 工具类,方便读写文件
     *
     * @author haozhang
     * @date 2020/09/04
     */
    public class FileUtil {
        /**
         * 读文件:一下把整个文件内容读到String中
         * @param filePath 表示要从哪读数据
         * @return
         */
        public static String readFile(String filePath) {
            //当涉及到编译错误,标准输出结果等文件内容都是文本文件。此处使用字符流方式来实现
            //try() ()中的内容是可以被自动关闭的
            try(FileReader fileReader = new FileReader(filePath);
                BufferedReader br = new BufferedReader(fileReader)) {
                StringBuilder sb = new StringBuilder();
                //按行读取文件内容
                String line = "";
                while ((line = br.readLine()) != null) {
                    sb.append(line);
                }
                return sb.toString();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }
    
        /**
         * 写文件:一下把String的内容写到指定文件中
         * @param filePath 表示要把数据写到哪个文件中
         * @param content 表示要写的文件内容
         */
        public static void writeFile(String filePath, String content) {
            try (FileWriter fw = new FileWriter(filePath)) {
                fw.write(content);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    

    5.4 题目增删查设计

    5.4.1 Problem对象设计

    package problem;
    
    /**
     * 每个problem对象就对应到oj_table中的一条记录
     *
     * @author haozhang
     * @date 2020/09/04
     */
    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 + '\'' +
                    '}';
        }
    }
    
    

    5.4.2 Problem对象操作设计

    package problem;
    
    import common.DBUtil;
    
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * 数据访问层
     *
     * @author haozhang
     * @date 2020/09/04
     */
    public class ProblemDAO {
    
        /**
         * 获取所有题目信息
         */
        public List<Problem> selectAll() {
            List<Problem> ret = new ArrayList<>();
            //1.获取数据库连接
            Connection connection = DBUtil.getConnection();
            //2.拼装sql语句
            String sql = "select * from oj_table";
            PreparedStatement statement = null;
            ResultSet resultSet = null;
            try {
                statement = connection.prepareStatement(sql);
                //3.执行sql语句
                resultSet = statement.executeQuery();
    
                //4.遍历结果集
                while (resultSet.next()) {
                    Problem problem = new Problem();
                    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"));
    //                problem.setTestCode(resultSet.getString("testCode"));
                    ret.add(problem);
                }
                return ret;
            } catch (SQLException e) {
                e.printStackTrace();
            } finally {
                //5.关闭连接
                DBUtil.close(connection, statement, resultSet);
            }
    
            return null;
        }
    
        /**
         * 获取指定id题目信息
         * @param id
         * @return
         */
        public Problem selectOne(int id) {
            //1.建立连接
            Connection connection = DBUtil.getConnection();
            //2.拼装sql语句
            String sql = "select * from oj_table where id = ?";
            PreparedStatement statement = null;
            ResultSet resultSet = null;
            try {
                statement = connection.prepareStatement(sql);
                statement.setInt(1, id);
                //3.执行sql语句
                resultSet = statement.executeQuery();
                //4.处理结果集
                if (resultSet.next()) {
                    Problem problem = new Problem();
                    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"));
                    problem.setTestCode(resultSet.getString("testCode"));
                    return problem;
                }
            } catch (SQLException e) {
                e.printStackTrace();
            } finally {
                //5.关闭连接
                DBUtil.close(connection, statement, resultSet);
            }
            return null;
        }
    
        /**
         * 新增一个题目到数据库中
         * @param problem
         */
        public void insert(Problem problem) {
            //1.获取连接
            Connection connection = DBUtil.getConnection();
            //2.拼装sql语句
            String sql = "insert into oj_table values (null, ?, ?, ?, ?, ?)";
            //3.执行sql语句
            PreparedStatement statement = null;
            try {
                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());
                statement.executeUpdate();
            } catch (SQLException e) {
                e.printStackTrace();
            } finally {
                //4.关闭连接
                DBUtil.close(connection, statement, null);
            }
        }
    
        /**
         * 删除指定id题目
         * @param id
         */
        public void delete(int id) {
            //1.建立连接
            Connection connection = DBUtil.getConnection();
            //2.拼接sql
            String sql = "delete from oj_table where id = ?";
            //3.执行sql
            PreparedStatement statement = null;
            try {
                statement.executeUpdate(sql);
            } catch (SQLException e) {
                e.printStackTrace();
            } finally {
    
                //4.关闭连接
                DBUtil.close(connection, statement, null);
            }
        }
    
        public static void main(String[] args) {
            String s11 = "abd";
            String s22 = "db2";
            StringBuilder sb3 = new StringBuilder(s11);
            sb3.reverse();
            Problem problem = new Problem();
            problem.setTitle("各位相加");
            problem.setLevel("简单");
            problem.setDescription("给定一个非负整数 num,反复将各个位上的数字相加,直到结果为一位数。\n" +
                    "\n" +
                    "示例:\n" +
                    "\n" +
                    "输入: 38\n" +
                    "输出: 2 \n" +
                    "解释: 各位相加的过程为:3 + 8 = 11, 1 + 1 = 2。 由于 2 是一位数,所以返回 2。\n" +
                    "\n");
            problem.setTemplateCode("public class Solution {\n" +
                    "    public int addDigits(int num) {\n" +
                    "\n" +
                    "    }\n" +
                    "}");
            problem.setTestCode(
                            "public static void main(String[] args) {\n" +
                            "    Solution s = new Solution();\n" +
                            "    if (s.addDigits(1) == 1 && s.addDigits(38) == 2) {\n" +
                            "        System.out.println(\"Test OK\");\n" +
                            "    } else {\n" +
                            "        System.out.println(\"Test Failed\");\n" +
                            "    }\n" +
                            "}\n");
    
            ProblemDAO problemDAO = new ProblemDAO();
            problemDAO.insert(problem);
            System.out.println("Insert OK");
    
    
            Problem problem1 = new Problem();
            problem1.setTitle("数字颠倒");
            problem1.setLevel("简单");
            problem1.setDescription("输入一个整数,将这个整数以字符串的形式逆序输出" +
                    "程序不考虑负数的情况,若数字含有0,则逆序形式也含有0,如输入为100,则输出为001\n" +
                    "\n" +
                    "示例:\n" +
                    "\n" +
                    "输入: 1516000\n" +
                    "输出: 0006151 \n" +
                    "解释: 将这个整数以字符串的形式逆序输出\n" +
                    "\n");
            problem1.setTemplateCode("public class Solution {\n" +
                    "    public String reverseNumber(int num) {\n" +
                    "\n" +
                    "    }\n" +
                    "}");
            problem1.setTestCode(
                    "public static void main(String[] args) {\n" +
                            "    Solution s = new Solution();\n" +
                            "    int num = 1516000000;        \n" +
                            "    String str = \"0000006151\"; \n" +
                            "    if (s.reverseNumber(num).equals(str)) {\n" +
                            "        System.out.println(\"Test OK\");\n" +
                            "    } else {\n" +
                            "        System.out.println(\"Test Failed\");\n" +
                            "    }\n" +
                            "}\n");
    
            ProblemDAO problemDAO1 = new ProblemDAO();
            problemDAO1.insert(problem1);
            System.out.println("Insert OK");
    
    
            Problem problem2 = new Problem();
            problem2.setTitle("字符串反转");
            problem2.setLevel("简单");
            problem2.setDescription("写出一个程序,接受一个字符串,然后输出该字符串反转后的字符串。(字符串长度不超过1000)\n" +
                    "\n" +
                    "示例:\n" +
                    "\n" +
                    "输入: abcd\n" +
                    "输出: dcba \n" +
                    "解释: 输出该字符串反转后的字符串\n" +
                    "\n");
            problem2.setTemplateCode("public class Solution {\n" +
                    "    public String reverseStr(String str) {\n" +
                    "\n" +
                    "    }\n" +
                    "}");
            problem2.setTestCode(
                    "public static void main(String[] args) {\n" +
                            "    Solution s = new Solution();\n" +
                            "    String str = \"abcdefghaaa\";\n" +
                            "    String rstr = \"aaahgfedcba\";\n" +
                            "    if (s.reverseStr(str).equals(rstr)) {\n" +
                            "        System.out.println(\"Test OK\");\n" +
                            "    } else {\n" +
                            "        System.out.println(\"Test Failed\");\n" +
                            "    }\n" +
                            "}\n");
    
            ProblemDAO problemDAO2 = new ProblemDAO();
            problemDAO2.insert(problem2);
            System.out.println("Insert OK");
    
    
    
    //        //2.测试selectAll
    //        ProblemDAO problemDAO = new ProblemDAO();
    //        List<Problem> problems = problemDAO.selectAll();
    //        System.out.println("selectAll:" + problems);
    //
    //        //3.测试selectOne
    //        ProblemDAO problemDAO = new ProblemDAO();
    //        Problem problem = problemDAO.selectOne(1);
    //        System.out.println(problem);
    
        }
    
    
    }
    
    

    5.5 api设计

    5.5.1 题目信息API

    package api;
    
    import com.google.gson.Gson;
    import com.google.gson.GsonBuilder;
    import problem.Problem;
    import problem.ProblemDAO;
    
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.util.List;
    
    /**
     *
     * @author haozhang
     * @date 2020/09/04
     */
    public class ProblemServlet extends HttpServlet {
        private Gson gson = new GsonBuilder().create();
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
            String id = req.getParameter("id");
            if (id == null || "".equals(id)) {
                //没有id这个参数, 执行查找全部
                selectAll(resp);
            } else {
                //存在id这个参数,执行查找指定题目id
                selectOne(Integer.parseInt(id), resp);
            }
        }
    
        private void selectOne(int problemId, HttpServletResponse resp) throws IOException {
            resp.setContentType("application/json; charset=utf-8");
            ProblemDAO problemDAO = new ProblemDAO();
            Problem problem = problemDAO.selectOne(problemId);
            //测试用例不应该被显示出来,手动改掉
            problem.setTestCode("");
            String json = gson.toJson(problem);
            resp.getWriter().write(json);
        }
    
        private void selectAll(HttpServletResponse resp) throws IOException {
            //ContentType 描述了body的数据类型是啥样的
            //常见取值
            //html:text/html
            //图片:image/png  image/jpg
            //json:application/json
            //css:text/css
            //javascript:application/javascript
            resp.setContentType("application/json; charset=utf-8");
            ProblemDAO problemDAO = new ProblemDAO();
            List<Problem> problems = problemDAO.selectAll();
    
            //把结果组织成json结构
            //注意:需要把problems中的某些字段去掉
            String jsonString = gson.toJson(problems);
            resp.getWriter().write(jsonString);
    
        }
    }
    
    

    5.5.2 提交运行API

    package api;
    
    import com.google.gson.Gson;
    import com.google.gson.GsonBuilder;
    import compile.Answer;
    import compile.Question;
    import compile.Task;
    import problem.Problem;
    import problem.ProblemDAO;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.io.InputStream;
    
    /**
     *
     * @author haozhang
     * @date 2020/09/06
     */
    public class CompileServlet extends HttpServlet {
        private Gson gson = new GsonBuilder().create();
    
        /**
         * 创建两个辅助的类,完成请求解析和响应构建
         *
         * 用来辅助解析 body 中的数据请求
         */
    
        static class CompileRequest {
            /**
             * 表示题目id
             */
            private int id;
    
            /**
             * 表示用户提交的代码
             */
            private String code;
    
            public int getId() {
                return id;
            }
    
            public void setId(int id) {
                this.id = id;
            }
    
            public String getCode() {
                return code;
            }
    
            public void setCode(String code) {
                this.code = code;
            }
        }
    
        /**
         * 用于构造最终响应数据
         */
        static class CompileResponse {
            /**
             * 表示是否成功
             */
            private int ok;
    
            /**
             *
             */
            private String reason;
    
            private String stdout;
    
            public int getOk() {
                return ok;
            }
    
            public void setOk(int ok) {
                this.ok = ok;
            }
    
            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;
            }
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
            //1.读取 请求 的 body 的所有数据
            String body = readBody(req);
    
            //2.按照API约定的格式来解析json数据,得到CompileRequest对象
            CompileRequest compileRequest = gson.fromJson(body, CompileRequest.class);
    
            //3.按照 id 从数据库中读取出对应的测试用例代码
            ProblemDAO problemDAO = new ProblemDAO();
            Problem problem = problemDAO.selectOne(compileRequest.getId());
    
            //得到该题目的测试代码
            String testCode = problem.getTestCode();
    
            //得到改题目的用户输入的代码
            String requestCode = compileRequest.getCode();
    
            //4.把用户输入的代码和测试用例进行组装,组装成一个完整的可以运行编译的代码
            String finalCode = mergeCode(requestCode, testCode);
    
            //5.创建task对象对刚才拼装的代码进行编译运行
            Question question = new Question();
            question.setCode(finalCode);
            question.setStdin("");
            Task task = new Task();
            Answer answer = null;
            try {
                answer = task.compileAndRun(question);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            //6.把运行结果构造成响应数据写回给客户端
            CompileResponse compileResponse = new CompileResponse();
            compileResponse.setOk(answer.getError());
            compileResponse.setReason(answer.getReason());
            compileResponse.setStdout(answer.getStdout());
            String jsonString = gson.toJson(compileResponse);
            resp.setContentType("application/json; charset=utf-8");
            resp.getWriter().write(jsonString);
    
        }
    
        /**
         * 把testCode中的main方法内容嵌入到requestCode中
         * @param requestCode 用户的代码
         * @param testCode 测试用例代码
         * @return
         */
        private String mergeCode(String requestCode, String testCode) {
            //合并之前考虑清楚这两部分的代码都是什么样的
            //1.先找到requestCode中最后一个 }
            //2.把requestCode中最后一个 } 删除之后,再把testCode内容拼接上
            //3.拼接完之后再补一个 }
            int pos = requestCode.lastIndexOf('}');
            if (pos == -1) {
                return null;
            }
    
            return requestCode.substring(0, pos) + testCode + "\n}";
        }
    
        private String readBody(HttpServletRequest req) {
            //body 的长度在 header 中的一个 Content-Length 字段中
            //contentLength 的单位就是字节
            int contentLength = req.getContentLength();
            byte[] buf = new byte[contentLength];
            try (InputStream is = req.getInputStream()) {
                is.read(buf, 0, contentLength);
            } catch (IOException e) {
                e.printStackTrace();
            }
    
            return new String(buf);
        }
    }
    
    

    六、webapp设计

    七、项目目录

    在这里插入图片描述

    八、项目改进

    1、引入用户管理(注册登录、每个人都做了哪写题)
    2、引入题目在线录入
    3、代码编辑框使用ace.js
    4、实现更严格的安全校验(假设用户在代码中写了一个删除所有文件的操作)

    九、项目源码

    项目github地址

    该项目最终是打包放在云服务器上的,关于云服务器配置安装相关环境的一些操作可以参考这篇博客!

    展开全文
  • 杭电oj 2072 java实现

    2020-10-27 16:07:24
    #杭电oj 2072 java 单词数 lily的朋友xiaoou333最近很空,他想了一件没有什么意义的事情, 就是统计文章文章里不同单词的总数。 下面你的任务是帮助xiaoou333解决这个问题。 这里一定要注意,是统计单词的个数,...

    #杭电oj 2072 java

    单词数

    lily的好朋友xiaoou333最近很空,他想了一件没有什么意义的事情,
    就是统计文章文章里不同单词的总数。
    下面你的任务是帮助xiaoou333解决这个问题。
    

    这里一定要注意,是统计单词的个数,有重复的就不算!!

    import java.util.*;
    public class Main {
    	public static void main(String[] args) {
    		Scanner sc=new Scanner(System.in);
    		while(sc.hasNext()) {
    			String str=sc.nextLine();//读入一行
    			String arr[]=str.split(" ");//用“ ”(空格)把字符串分开
    			boolean flag=false;//标志位,true则有#,false没有#
    			for(int i=0;i<arr.length;i++) {
    				if(arr[i].contains("#")) {
    					flag=true;//循环判断是否有#
    				}
    			}
    			if(flag)break;
    			ArrayList<String> arr1=new ArrayList<String>();
    			for(int i=0;i<arr.length;i++) {
    				if(!arr1.contains(arr[i])) {
    					arr1.add(arr[i]);//如果原ArrayList没有这个单词,就加入
    				}
    			}
    			if(arr1.contains("")) {//如果ArrayList里有“”,则数量是ArrayList-1,比如字符串的第一个字符就是" "的时候
    				System.out.println(arr1.size()-1);//比如字符串的第一个字符就是" "的时候
    			}else {
    				System.out.println(arr1.size());
    			}
    		}
    	}
    }
    
    展开全文
  • 杭电oj 2020 java实现

    2020-10-20 21:51:39
    #杭电oj 2020 java 绝对值排序 输入n(n <= 100)个整数,按照绝对值从大到小排序后输出。 转换保证对于每一个测试实例,所有的数的绝对值都不选择。 import java.util.*; public class Main { public static ...

    #杭电oj 2020 java

    绝对值排序

    输入n(n <= 100)个整数,按照绝对值从大到小排序后输出。
    转换保证对于每一个测试实例,所有的数的绝对值都不选择。
    
    import java.util.*; 
    public class Main {
    	public static void main(String[] args) {
    		Scanner sc = new Scanner(System.in);
    		while (sc.hasNext()) {
    			int n=sc.nextInt();//排头 n个整数
    			if(n==0) {//n = 0表示输入数据的结束,不做处理。 
    				break;
    			}
    			int[] arr=new int[n];//存放输入的n个整数
    			for(int i=0;i<arr.length;i++) {
    				arr[i]=sc.nextInt();
    			}
    			for(int i=0;i<arr.length-1;i++) {
    				for(int j=i+1;j<arr.length;j++) {
    					if(Math.abs(arr[j])>Math.abs(arr[i])) {
    						//进行选择排序
    						//Math.abs()表示绝对值
    						int t=arr[j];
    						arr[j]=arr[i];
    						arr[i]=t;
    					}
    				}
    			}
    			for(int i=0;i<arr.length-1;i++) {//输出前n-1个
    				System.out.print(arr[i]+" ");
    			}
    			System.out.println(arr[arr.length-1]);//输出最后一个,换行
    		}
    	}
    }
    
    
    展开全文
  • 杭电oj 2017 java实现

    2020-10-19 21:20:58
    #杭电oj 2017 java 官方统计 对于给定的一个字符串,统计其中数字字符出现的次数。 import java.util.*; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in);...
  • 杭电oj1003java实现

    千次阅读 2018-03-20 16:11:40
    java . util . Scanner ; public class 杭电 1003d p { public static void main ( String [ ] args ) { Scanner sc = new Scanner ( System . in ) ; int t = sc . nextInt ( ) ; ...
  • Java OJ常用输入写法

    2020-09-18 10:26:09
    平时如果刷LeetCode刷的比较多,会忘记输入输出怎么写诶 在开学上机考试前特地花1个多小时整理了Java版的输入写法 一.输入一个数、两个数 //一.【一个数、两个数】 Scanner sc = new Scanner(System.in); int m=...
  • 华为OJ&答案(java版)1. 功能:等差数列 2,5,8,11,14。。。。输入:正整数N >0输出:求等差数列前N项和返回:转换成功返回 0 ,非法输入与异常返回-1public static void main(String[] args){try{new Scanner...
  • 1.把类名改为Main 2.一般情况下只存在一个Main类,如果想要多个类,其他类你、不能用Public修饰符修饰(接口也一样)。
  • 杭电oj2000题(java

    2021-03-27 20:30:31
    HDU2000 – java 2000题 import java.util.Arrays; import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner s=new Scanner(System.in); while(s.hasNext()) { ...
  • OJ系统Java语言编程技巧常见题型:最常见题型还是依赖于数组和字符串,需要熟练的操作,而java针对数组还有字符串都提供了大量的方法。可以简化编程,同时也是对编程语言的一种掌握。下面罗列一些自己经常遇到很好用...
  • 杭电oj 2008 java实现

    2020-10-17 20:22:28
    #杭电oj 2008 java 数值统计 统计给定的n个数中,负数,零和正数的个数。 import java.util.*; public class Main { public static void main(String[] args) { Scanner sc=new Scanner(System.in); while(sc....
  • Java提交OJ规范

    千次阅读 2019-07-15 11:10:46
    首先我们需要很明确的一点是在类vjude这种OJ提交系统中一般都是需要循环输入的,即他会用多行输入来去测试你的程序是否正确。 这是A题:题目中提供了问题,输入格式要求,输出格式要求,输入样例,输出样例,需要...
  • 杭电oj2072,2091字符串java实现

    千次阅读 2018-03-10 21:08:20
    思路:输入String,使用字符串分割,分割成小的字符数组,使用java的List储存不同单词,每次比较若全部不同则存入,返回List长度注意:不要用数组,数组长度无法改变并且数组处理空字符串和回车会很麻烦,附上代码 ...
  • 杭电oj 2010 java实现

    2020-10-17 22:11:40
    #杭电oj 2010 java 水仙花数 春天是鲜花的季节,水仙花就是其中最迷人的代表, 数学上有个水仙花数,他是这样定义的: “水仙花数”是指一个三位数,它的各位数字的立方和等于其本身, 例如:153 = 1 ^ 3 + 5 ^ 3 + ...
  • 项目名称:在线 oj 系统 项目背景: 每一个学习编程的同学都有一个大厂梦,要实现自己的梦想,平时的练习就必不可少。平时的刷题是必不可少的,力扣网和牛客网是我平时刷题的两个网站。里边的功能深深的吸引了我,...
  • OJ中提交Java程序的一些套路

    千次阅读 2018-10-30 10:28:40
    //用完后关闭扫描器是一个的习惯 } } Scanner处理输入: Scanner在处理字符串对象的时候,如果使用 next 函数,默认以 空格 或者 回车换行符 作为分隔。比如上面这段程序,当我们输入为 ...
  • 杭电oj 1001 java

    2019-03-17 17:17:50
    import java.util.Scanner; class Main { public static void main(String[] args) { // TODO Auto-generated method stub Scanner read = new Scanner(System.in); while(read.hasNex...
  • 在刷OJ时,题目常常需要我们从键盘输入来获取值,这些会是整数,浮点数,字符串等。在刷完一定的题量后(博主一般使用java刷题),对其进行总结是很有必要的。常用来从键盘输入获取值的三个类:Scanner,...
  • Java_OJ- 项目介绍 功能简介 模仿 Leetcode 和牛客网的在线OJ功能,实现的一个基于Java语言使用者的在线OJ项目。 核心功能 展示题目库中所有题目 对某一题目进行详细展示 对用户提交的代码进行编译运行 功能模块 ...
  • oj1199.java

    2020-07-26 16:12:24
    在一个N*N的方阵中,填入1,2,……N 共N个数,并要求构成如下的格式:N, 例: N=4 10 11 12 1 9 16 13 2 8 15 14 3 7 6 5 4 输入 多组数据,每行读入一个N. ...每个测试案例之间有一个空行
  • JavaOJ中常用的各种输入

    千次阅读 2018-05-07 14:13:47
    1. 只有一组数据: Scanner s=new Scanner(System.in); int a=s.nextInt(); int b=s.nextInt(); 2. 输入多组数据,不告知组数,也没有截止符 ...Scanner s=new Scanner(System.in);...while(s.hasNext()){//判断是否...
  • JavaOJ平台提交的方式与基本套路

    千次阅读 2019-03-09 10:16:47
    JavaOJ平台提交的方式与基本套路 第一次用Java提交Oj题目,发现比C++麻烦不少,C++ 写完放在OJ上大多数都能够直接跑,但Java甚至出现了编译错误这种情况,因此,需要对自己的程序做不少的修改。 比如说,个人第...
  • OJ输入输出,java版本

    2020-06-01 00:36:17
    a+b(1) public static void main(String[] args) { Scanner cin = new Scanner(System.in); int N, M; // 读取输入,直到没有整型数据可读 while (cin.hasNextInt()) { int a = cin.nextInt();...
  • OJ java规范

    2017-02-26 22:28:24
    Java:必须是public class Main提交,并且不能带包名,输入和输出的格式一定要按照题目要求的去写,否则提交不过。输入不可用文件输入。使用 Scanner sc=new Scanner(System.in); 1. 多组数据,每组数据一...
  • 杭电oj 2001 java

    2019-03-17 17:26:42
    import java.util.Scanner; class Main { public static void main(String[] args) { // TODO Auto-generated method stub Scanner read = new Scanner(System.in); while(read.hasNe...
  • 大部分常见OJ要求只能提交一个源代码段落,即只能有一个.java文件。通常文件命名为Main,程序入口为public static void main().而Java要求public的类必须与所在文件同名。因此只能是 public class Main{ public ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 24,718
精华内容 9,887
关键字:

java比较好的oj

java 订阅