很纳闷的一个问题,通过配置文件生成的java源码在本地动态编译没有问题,但是部署服务器后编译不通过,找不到依赖的jar包。
通过网上查资料,找到一个兄弟提供的方法,问题解决了;下面贴出代码以供参考:
package com.songxingzhu.utils.compile;
import org.apache.commons.io.FileUtils;
import com.songxingzhu.utils.context.AppContext;
import com.songxingzhu.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;
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;
}
}
}
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;
}
}
}
个人理解:部署后不像eclipse编译有.classpath指向依赖的所有的jar,需要自己组装类似classpath,指定jar包路劲。重点是设置option,不懂option的可以通过cmd命令查看javac的参数介绍。
其中,option.add("-classpath");就是类似直接运行javac -classpath 类文件