一、问题
动态编译java文件时(这个java文件虽引用了第三方jar包),如果这个过程发生在java命令行程序中,则正常编译。如果发生在JavaWeb中,然后此Java部署到Tomcat之后,执行动态编译时,就会提示找不到相关类或者Jar。
二、解决方案
将所依赖到的Jar文件,复制到%JAVA_Home%\jre\lib\ext目录下。 例如:C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext 再重启Tomcat。
三、解决方法二:
编译时,添加classPath参数,即可,DEMO代码很乱,参考如下:
package servlets; import com.github.henryhuang.dynamiccompiler.ClassGenerator; import domain.MyJavaSourceFromString; import org.apache.commons.io.FileUtils; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.tools.JavaCompiler; import javax.tools.JavaFileManager; import javax.tools.JavaFileObject; import javax.tools.ToolProvider; import java.io.File; import java.io.IOException; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class MyServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { try { String buildOutput = MyServlet.class.getProtectionDomain().getCodeSource().getLocation().getPath(); File f = new File("D:\\Project\\JavaProject\\dynamicompileInWeb\\out\\artifacts\\web_war_exploded", "WEB-INF\\TestCode.java"); String code = FileUtils.readFileToString(f, "UTF-8"); resp.getWriter().write(code); // instantiate the Java compiler JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); JavaFileManager fileManager = compiler.getStandardFileManager(null, null, null); // load the uploaded files into the compiler Listfiles = new ArrayList (); //files.add(new ByteArrayJavaFileObject(fullName, patchFile.getBytes())); files.add(new MyJavaSourceFromString("TestCode", code)); // set the classpath List options = new ArrayList (); options.add("-classpath"); StringBuilder sb = new StringBuilder(); URLClassLoader urlClassLoader = (URLClassLoader) Thread.currentThread().getContextClassLoader(); for (URL url : urlClassLoader.getURLs()) { sb.append(url.getFile()).append(File.pathSeparator); } options.add(sb.toString()); options.add("-d"); options.add(buildOutput); // execute the compiler boolean isok = compiler.getTask(null, fileManager, null, options, null, files).call(); System.out.println(isok); File root = new File(buildOutput); if (!root.exists()) root.mkdirs(); URL[] urls = new URL[]{root.toURI().toURL()}; URLClassLoader classLoader = URLClassLoader.newInstance(urls); Class> clazz2 = Class.forName("TestCode", true, classLoader); // instantiate the class (FAILS HERE) //Object instance = fileManager.getClassLoader(null).loadClass("TestCode").newInstance(); // close the file manager fileManager.close(); // //if (clazz != null) { // resp.getWriter().write("\r\n" + clazz + ":compile success."); //} else { // resp.getWriter().write("\r\n" + clazz + ":compile failed."); //} } catch (Exception ex) { resp.getWriter().write(ex.getMessage()); } } }
简单封装
package yungoal.huafeng.utils.compile; import org.apache.commons.io.FileUtils; import yungoal.huafeng.utils.context.AppContext; import javax.tools.JavaCompiler; import javax.tools.JavaFileManager; import javax.tools.JavaFileObject; import javax.tools.ToolProvider; import java.io.File; import java.io.IOException; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; import java.util.List; public class ClassBuilder { public static Class> buildClass(String fullClassName, String codeFilePath) throws IOException, ClassNotFoundException { return buildClass(fullClassName, codeFilePath, "UTF-8", AppContext.baseDirectory()); } public static Class> buildClass(String fullClassName, String codeFilePath, String charsetName, String buildOutput) throws IOException, ClassNotFoundException { try { String code = FileUtils.readFileToString(FileUtils.getFile(codeFilePath), charsetName); JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); JavaFileManager fileManager = compiler.getStandardFileManager(null, null, null); Listfiles = new ArrayList<>(); files.add(new JavaSourceFromCodeString(fullClassName, code)); List options = new ArrayList<>(); options.add("-classpath"); StringBuilder sb = new StringBuilder(); URLClassLoader urlClassLoader = (URLClassLoader) Thread.currentThread().getContextClassLoader(); for (URL url : urlClassLoader.getURLs()) { sb.append(url.getFile()).append(File.pathSeparator); } options.add(sb.toString()); options.add("-d"); options.add(buildOutput); // execute the compiler boolean isok = compiler.getTask(null, fileManager, null, options, null, files).call(); if (isok) { File root = new File(buildOutput); if (!root.exists()) root.mkdirs(); URL[] urls = new URL[]{root.toURI().toURL()}; ClassLoader classLoader = ClassBuilder.class.getClassLoader(); Class> clazz = Class.forName(fullClassName, true, classLoader); return clazz; } return null; } catch (Exception ex) { throw ex; } } }