我有一个使用Maven引用“示例库”的现有“示例Webapp”。我正在使用m2e插件在Eclipse 4.3RC3中运行Tomcat 7。当我在Eclipse内部的Tomcat上启动Example Webapp时,我已经验证example-library.jar
可能已部署在Tomcat实例的WEB-INF/lib
文件夹中。
示例Webapp具有使用JavaCompiler.CompilationTask
动态编译某些类的代码。这些动态生成的类引用example-library.jar
中的类。不幸的是,编译任务失败了,因为找不到引用的类。
我知道我可以set the JavaCompiler
classpath,但System.getProperty("java.class.path")
只返回Tomcat类路径,而不是webapp类路径:
C:\bin\tomcat\bin\bootstrap.jar;C:\bin\tomcat\bin\tomcat-juli.jar;C:\bin\jdk6\lib\tools.jar
其他有said我需要从servlet上下文中获取WEB-INF/lib
的真实路径,但是类生成代码对servlet上下文一无所知 - 它被写入不知道它是在客户端还是在服务器上使用。
在another question中,有一个answer表示我可以枚举类加载器网址,这肯定会为我提供WEB-INF/lib
中的jar,但当我将其作为{{1}提供时-classpath
的选项,任务仍然失败,因为它找不到引用的类。
如何简单地将当前正在执行的代码的类路径提供给compiler.getTask()
实例,以便它可以从JavaCompiler
中的库中找到类? (similar question引发了{{3}}但从未回答有关使用WEB-INF/lib
引用ear文件中的jar文件的问题。)
示例:为了不惜任何代价让事情变得有效,我甚至尝试对类路径进行硬编码。例如,我的webapp lib目录中有JavaCompiler
,所以我使用了以下代码,根据我上面指出的答案进行了修改:
foobar.lib
最后List<String> options = new ArrayList<String>();
options.add("-classpath");
options.add("C:\\work\\.metadata\\.plugins\\org.eclipse.wst.server.core\\tmp0\\wtpwebapps\\FooBar\\WEB-INF\\lib\\foobar.jar");
JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, diagnostics, options, null, compilationUnits);
boolean success = task.call();
为success
,我的false
表示diaognostics
,即使该包位于package com.example.foo.bar does not exist...
。
答案 0 :(得分:1)
将example-library.jar放在文件系统中的某个位置,并将该位置传递给运行JavaCompiler的代码(-classpath选项)。如果使用爆炸的WAR文件进行部署,您当然可以将其指向WEB-INF / lib文件夹中的物理位置。关键是您只需要在webapp中使用一个可配置参数来执行此操作,这可以是属性文件条目,-D系统属性,数据库行或其他完全。
示例代码(在Tomora 7和Fedora 18 x64上的OpenJDK 1.7中测试):
private File compile(File javaFile, String classpath) throws IOException {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
Iterable<? extends JavaFileObject> compilationUnit = fileManager.getJavaFileObjects(javaFile);
List<String> options = classpath != null ? Arrays.asList("-classpath", classpath) : null;
StringWriter output = new StringWriter();
try {
boolean successful = compiler.getTask(output, fileManager, null, options, null, compilationUnit).call();
if (!successful) {
throw new CompilationException("Failed to compile: " + javaFile, output.toString());
}
return firstClassFileFrom(javaFile.getParentFile());
} finally {
fileManager.close();
}
}
private File firstClassFileFrom(File directory) {
return directory.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.endsWith(".class");
}
})[0];
}
有关可运行的示例网络应用,请参阅https://github.com/jpalomaki/compiler。
答案 1 :(得分:0)
我的代码:
String classpath ="xx/WEB-INF/clases ";
List<String> options = classpath != null ? Arrays.asList("-d", classpath,"-cp",classpath) : null;
CompilationTask task = compiler.getTask(null, javaDinamicoManager, diagnostics,
options, null, Arrays.asList(sourceObj));
boolean result = task.call();
“结果”将返回true。
答案 2 :(得分:0)
您可以按照提供的答案提供更具体的问题,即如何从直接从未扩展的WAR文件运行的Web应用程序中加载已编译代码的依赖关系(没有要引用的JAR文件 - 只有容器&#39; s class loder知道如何访问类):https://stackoverflow.com/a/45038007/2546679