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 才有效。

    运行效果

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

  • 相关阅读:
    现阶段学习窘境总结(2013年6月21日-至今)
    MvcPager 分页控件
    JS 实现PDF文件打印
    json和Jsonp 使用总结(1)
    实战篇之存储过程的使用
    ASP.NET MVC5 之 客户端实现文件的下载
    WMI 技术
    PowerDesigner 的使用教程
    Rose
    对路径 obj 文件夹访问被拒绝
  • 原文地址:https://www.cnblogs.com/liaoyu/p/real-time-compile-and-run-java-code-web-app.html
Copyright © 2011-2022 走看看