我的理解是,无论在什么web容器下,新增加的类都得放到容器的URLClassLoader 下,
因此,在使用JavaCompiler 时,需在options 中为类指定正确的输出路径。
public static Class complieJavaFileToClass(File javafile, File classRootDir, String packageName,
File[] retClsFile) {
System.out.println(" javafile=" + javafile.getName());
{
JavaCompiler jc = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager sm = jc.getStandardFileManager(null, null, null);
String filename = javafile.getName();
String sclsName = filename.substring(0, filename.length() - 5);
String clsName = packageName + "." + sclsName;
File expectClsFile = new File(classRootDir, clsName.replace('.', '/') + ".class");
try {
List options = new ArrayList(3);
{//指定类的输出路径、其它类路径(若不指定,布置到web上后,动态编译无法找到相关类)
boolean foundClassDir = false;
options.add("-classpath");
StringBuilder sb = new StringBuilder();
URLClassLoader urlClassLoader = (URLClassLoader) Thread.currentThread().getContextClassLoader();
String D = classRootDir.toURI().toURL().getFile();
for (URL url : urlClassLoader.getURLs()) {
String file = url.getFile();
if (!foundClassDir) {
//发现在eclilpse下的tomcat部署,需要把生成类加到特定路径下。
File curClassRoot = new File(file);
if (curClassRoot.isDirectory()) {
classRootDir = curClassRoot;
expectClsFile = new File(classRootDir, clsName.replace('.', '/') + ".class");
foundClassDir = true;
}
}
sb.append(file).append(File.pathSeparator);
}
options.add(sb.toString());
options.add("-d");
options.add(classRootDir.getAbsolutePath());
}
Iterable extends JavaFileObject> it = sm.getJavaFileObjects(javafile);
JavaCompiler.CompilationTask task = jc.getTask(null, sm, null, options, null, it);
if (!task.call()) {
System.err.println("failed.");
return null;
}
ClassLoader classLoader = null;
sm.close();
return Class.forName(clsName);
} catch (Exception e) {
try {
URL[] urls = new URL[] { expectClsFile.toURI().toURL() };
ClassLoader load = Misc9.class.getClassLoader();
Class> clazz = Class.forName(clsName, false, load);//不清楚有啥特别的
return clazz;
} catch (Exception ee) {
ee.printStackTrace();
}
return null;
} finally {
}
}
}