4

我有一个现有的“示例 Webapp”,它使用 Maven 引用“示例库”。我在 Eclipse 4.3RC3 中使用 m2e 插件运行 Tomcat 7。当我在 Eclipse 内的 Tomcat 上启动 Example Webapp 时,我已经验证它example-library.jar可能已部署在 Tomcat 实例的WEB-INF/lib文件夹中。

示例 Webapp 具有使用JavaCompiler.CompilationTask. 这些动态生成的类引用example-library.jar. 不幸的是,编译任务失败,因为找不到引用的类。

我知道我可以设置JavaCompilerclasspath,但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

其他人我需要WEB-INF/lib从 servlet 上下文中获取真正的路径,但是类生成代码对 servlet 上下文一无所知 --- 它被编写为不知道它是在客户端还是在客户端上使用服务器。

另一个问题中,一个答案表明我可以枚举类加载器 URL,果然这为我提供了 jars WEB-INF/lib,但是当我将其作为-classpath选项提供时compiler.getTask(),任务仍然失败,因为它找不到引用的类。

如何简单地将当前执行代码的类路径提供给JavaCompiler实例,以便它从库中找到类WEB-INF/lib?(提出了一个类似的问题,但从未回答有关使用 .ear 文件中引用 jar 的问题JavaCompiler。)

示例:为了不惜一切代价让事情正常进行,我什至尝试对类路径进行硬编码。例如,我foobar.lib在我的 webapp 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();

最后successfalse,我diaognostics表示package com.example.foo.bar does not exist...,即使那个包在foobar.jar.

4

3 回答 3

1

将 example-library.jar 放在文件系统中的某个位置,并将该位置传递给运行 JavaCompiler 的代码(-classpath 选项)。如果使用展开的 WAR 文件进行部署,当然可以将其指向 WEB-INF/lib 文件夹中的物理位置。关键是您只需要在您的 web 应用程序中配置一个参数来执行此操作,它可以是属性文件条目、-D 系统属性、数据库行或其他东西。

示例代码(在 Fedora 18 x64 上的 Tomcat 7 和 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];
}

有关可运行的示例 web 应用程序,请参阅https://github.com/jpalomaki/compiler

于 2013-06-09T19:24:46.740 回答
0

我遇到了同样的问题。原因不是 "-classpath" 。

我的代码:

   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 。

于 2014-09-17T03:51:28.600 回答
0

您可以遵循为更具体的问题提供的答案,即如何从直接从未扩展的 WAR 文件运行的 Web 应用程序中加载已编译代码的依赖项(没有要引用的 JAR 文件 - 只有容器的类加载器知道如何访问类):https ://stackoverflow.com/a/45038007/2546679

于 2017-07-11T14:58:50.400 回答