页面上动态编译及执行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("\n");

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-INF\classes下即可:

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

运行效果

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

以上是 页面上动态编译及执行java代码 的全部内容, 来源链接: utcz.com/z/392835.html

回到顶部