Java Web部署到tomcat后,使用动态编译无法找到相关类的解决方案
Java Web部署到tomcat后,使用动态编译无法找到相关类的解决方案
一、问题
动态编译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
List<JavaFileObject> files = new ArrayList<JavaFileObject>();
//files.add(new ByteArrayJavaFileObject(fullName, patchFile.getBytes()));
files.add(new MyJavaSourceFromString("TestCode", code));
// set the classpath
List<String> options = new ArrayList<String>();
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 com.test.utils.compile;
import org.apache.commons.io.FileUtils;
import com.test.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);
List<JavaFileObject> files = new ArrayList<>();
files.add(new JavaSourceFromCodeString(fullClassName, code));
List<String> 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;
}
}
}
Java Web部署到tomcat后,使用动态编译无法找到相关类的解决方案
https://www.dearcloud.cn/2018/05/02/20200310-cnblogs-old-posts/20180502-JavaWeb部署到tomcat后,使用动态编译无法找到相关类的解决方案/