zoukankan      html  css  js  c++  java
  • 页面上动态编译及执行java代码

    本文地址:http://www.cnblogs.com/liaoyu/p/real-time-compile-and-run-java-code-web-app.html

    最近看到同事在页面上编译和执行java代码,有点像Web IDE,感觉很酷就试着自己实现下。

    预期要实现以下几个功能:

    1. 页面上使用textarea作为简单的代码编辑器,通过单击执行按钮向服务器发送请求
    2. 服务器端接收到java代码,进行简单的校验,若检验通过则进行编译
    3. 如果编译错误,返回异常信息
    4. 重定向代码中的system.out输出,将结果返回到客户端

    相关实现

    public class RuntimeCompiler {
    
        private List<String> options = null;
        private JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        private DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
        private StringBuffer traceMsg = new StringBuffer();
    
        public RuntimeCompiler(String... options) {
            // inital compile params
            if (options != null && options.length > 0) {
                this.options = Arrays.asList(options);
            }
        }
    
        public boolean compile(String className, String code) {
            JavaFileObject sourceFile = new StringJavaFileObject(className, code);
            Iterable<? extends JavaFileObject> compilationUnits = Arrays.asList(sourceFile);
            CompilationTask task = compiler.getTask(null, null, diagnostics, options, null, compilationUnits);
            boolean result = task.call();
    
            // Record compile error messages
            for (Diagnostic<?> diagnostic : diagnostics.getDiagnostics()) {
                traceMsg.append(diagnostic.getMessage(null)).append("
    ");
                traceMsg.append(String.format("Error on line %d in %s%n", diagnostic.getLineNumber(),
                        ((FileObject) diagnostic.getSource()).toUri()));
            }
    
            return result;
        }
    
        public String getTraceMsg() {
            return traceMsg.toString();
        }
    }
    

    编译时需指定生成的.class文件的路径,由于是在tomcat作为服务器,存在到WEB-INFclasses下即可:

    String realPath = request.getServletContext().getRealPath("/") + "WEB-INF\classes";
    RuntimeCompiler rc = new RuntimeCompiler("-d", realPath);
    boolean success = rc.compile(className, code);
    

    在使用反射执行该类时,需将System.out的输出重定向到ByteArrayOutputStream,最后将该结果返回到客户端

    // Create a stream to hold the output
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    PrintStream printStream = new PrintStream(baos);
    // Tell Java to use your special stream
    System.setOut(printStream);
    
    if (success) {
        try {
            Class.forName(fullClassName).getDeclaredMethod("main", new Class[] {
                String[].class
            }).invoke(null, new Object[] {
                null
            });
        } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException
                | InvocationTargetException e) {
            result = "Load class error: " + e;
        }
    }
    
    // flush output stream 
    System.out.flush();
    out.print(baos.toString());
    

    我在页面中是使用angularjs来实现交互,发现angularjs无法通过在 textarea 标签里边来设置默认值,只好用指令 ng-model 绑定变量,在controller中设置初始值。

    目前存在的问题

    当在页面上的修改同一个类时,连续点击run,会有10秒左右的延迟,这是由于它会编译成内容不同的.class文件,只有当 org.apache.catalina.core.StandardContext reload 才有效。

    运行效果

    查看完整源代码:点击这里

  • 相关阅读:
    1052 Linked List Sorting (25 分)
    1051 Pop Sequence (25 分)
    1050 String Subtraction (20 分)
    1049 Counting Ones (30 分)
    1048 Find Coins (25 分)
    1047 Student List for Course (25 分)
    1046 Shortest Distance (20 分)
    1045 Favorite Color Stripe (30 分)
    1044 Shopping in Mars (25 分)
    1055 The World's Richest (25 分)
  • 原文地址:https://www.cnblogs.com/liaoyu/p/real-time-compile-and-run-java-code-web-app.html
Copyright © 2011-2022 走看看