JSP 在 Windows 上使用 IntelliJ IDEA 生成的动态类路径时编译失败

JSP compilation fails when using dynamic classpath generated by IntelliJ IDEA on Windows

我有一个 Spring/MVC/Tomcat 网站项目,我正在尝试 运行 使用 IntelliJ IDEA。因为我在 Windows 上 运行ning,所以存在命令行大小限制,大型类路径超出了该限制。我使用 IntelliJ 的动态类路径功能,该功能将类路径放在 jar 文件中以缩短命令行。 Java 运行 与 -classpath <classpath.jar>.

当我尝试查看页面时,JSP 编译失败并出现错误:

org.apache.jasper.JasperException: Unable to compile class for JSP: 

An error occurred at line: [-1] in the generated java file: [<removed>.java]
    [javac] <removed>.java:11: error: package javax.servlet does not exist
    [javac] import javax.servlet.*;
    [javac] ^

我 运行 它处于调试状态,并进入 java 编译的位置,发现使用了 javac 命令行。它被放在一起 org.apache.tools.ant.taskdefs.compilers.JavacExternal。我 运行 javac 命令自己,使用 -verbose,并注意到来自 search path for class files: 日志行的依赖路径显示为:

C:\Users\<removed>\AppData\Local\Temp\file:\C:\Users\<removed>\lib\servlet-api-3.0.jar

请注意,绝对 URI 路径似乎被视为相对路径,导致路径无效。我相信这就是它无法正确编译的原因。

Intellij 生成的路径 jar 的 MANIFEST.MF 列出类路径,其中的条目是绝对路径,如下所示:

file:/C:/Program%20Files/Java/jdk1.8.0_121/jre/lib/charsets.jar file:/C:/Program%20Files/Java/jdk1.8.0_121/jre/lib/deploy.jar [...]

这个问题不会在 Mac 上发生,使用动态类路径 jar(即使没有必要,因为命令行太长的错误不会发生)所以我相信 Windows路径或 IntelliJ 在 Windows 上生成类路径 jar 的方式搞乱了 JSP 编译。

此外,使用生成具有相对路径的路径 jar 的 Ant 构建任务也可以,但我有兴趣避免在此处使用 Ant。

我怎样才能让它工作,或者我还需要调查什么才能找到根本原因?

这是一个known bug in JDK

Javac 错误地处理清单类路径中的绝对路径 headers。 JDK9已经修复了。

当我调查这个问题时,假设 Java8,我在我的案例中发现了不同的根本原因。

简而言之:

  • 第 102 行的“/org/apache/jasper/servlet/TldScanner.java”尝试扫描潜在 JAR 的位置。
  • 它使用“/org/apache/tomcat/util/scan/StandardJarScanner.java”来实际搜索。
  • 在第 221 行打断点URL[] urls = ((URLClassLoader) classLoader).getURLs();
  • 您将看到此 ClassLoader 具有 "classpath.jar" 作为要扫描(即处理)的潜在 JAR。
  • 但它无法进一步找到 (classpath.jar) JAR 清单文件引用的 JAR。意思是,您需要的真正 JAR 不会被检查。

一个简短的修复方法是:

  • 将 "standard-1.1.2.jar" 添加到您的 web/WEB-INF/lib/ 目录。
  • 如果您查看此 jar 内部,您将看到 *.tld 文件。

测试:

  • 您可以在 TldScanner.java 第 311 行 found = true; 上放置一个断点。
  • 当它不起作用时,你永远不会点击这条线。
  • 当它工作时,通过这个(或任何)修复,它会命中这一行。