在Tomcat 8.5 Startup期间从Spring boot 1.2升级到1.5.2,FileNotFoundException

Sun*_*amy 20 spring spring-boot tomcat8.5

Spring Boot从1.2.0 升级1.5.2.

升级之后,Tomcat 8.5启动期间抛出FileNotFoundException.

下面是其中一个例外,它引发了超过10个类似的例外.

我不知道这些罐子的用途,换句话说,我没有<dependency>pom.xml中添加这些罐子.

INFO: Starting Servlet Engine: Apache Tomcat/8.5.11
Apr 06, 2017 3:53:57 PM org.apache.tomcat.util.scan.StandardJarScanner scan
WARNING: Failed to scan [file:/C:/Users/myname/.m2/repository/com/sun/xml/ws/jaxws-rt/2.1.7/jaxws-api.jar] from classloader hierarchy
java.io.FileNotFoundException: C:\Users\myname\.m2\repository\com\sun\xml\ws\jaxws-rt\2.1.7\jaxws-api.jar (The system cannot find the file specified)
    at java.util.zip.ZipFile.open(Native Method)
    at java.util.zip.ZipFile.<init>(ZipFile.java:219)
    at java.util.zip.ZipFile.<init>(ZipFile.java:149)
    at java.util.jar.JarFile.<init>(JarFile.java:166)
    at java.util.jar.JarFile.<init>(JarFile.java:130)
    at org.apache.tomcat.util.scan.JarFileUrlJar.<init>(JarFileUrlJar.java:60)
    at org.apache.tomcat.util.scan.JarFactory.newInstance(JarFactory.java:48)
    at org.apache.tomcat.util.scan.StandardJarScanner.process(StandardJarScanner.java:338)
    at org.apache.tomcat.util.scan.StandardJarScanner.scan(StandardJarScanner.java:288)
    at org.apache.jasper.servlet.TldScanner.scanJars(TldScanner.java:262)
    at org.apache.jasper.servlet.TldScanner.scan(TldScanner.java:104)
    at org.apache.jasper.servlet.JasperInitializer.onStartup(JasperInitializer.java:101)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5178)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1419)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1409)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
Run Code Online (Sandbox Code Playgroud)

任何帮助,将不胜感激.

Sun*_*amy 30

根本原因:

根据Tomcat Wiki,Servlet 3.0规范要求在服务器启动期间进行Jar扫描.

Tomcat正在使用org.apache.tomcat.util.scan.StandardJarScanner用于此目的.

来自StandardJarScanner的javadoc .

默认的JarScanner实现扫描WEB-INF/lib目录,然后扫描提供的类加载器,然后处理类加载器层次结构.此实现足以满足Servlet 3.0规范的要求以及提供许多Tomcat特定扩展.扩展名是:

  • 扫描类加载器层次结构(默认情况下启用)测试所有文件以查看它们是否为JAR(默认情况下禁用)

  • 测试所有目录以查看它们是否是爆炸JAR(默认情况下禁用)

  • 可以通过配置来控制所有扩展.

Solution1:特定于Spring Boot.

我们可以禁用此jar扫描.

我通过在application-xxx.properties文件中添加以下属性来禁用它.此属性是特定于Spring Boot的.

# Comma-separated list of additional patterns that match jars to ignore for TLD scanning.    
server.tomcat.additional-tld-skip-patterns=*.jar
Run Code Online (Sandbox Code Playgroud)

您可以在这里找到Tomcat的类似房产 .

这些属性可用于配置传统的 tomcat( spring启动)应用程序.

解决方案2:特定于Spring

您可以为清单文件禁用JarScanner,如下所示.

@Bean
public EmbeddedServletContainerFactory embeddedServletContainerFactory() {
  return new TomcatEmbeddedServletContainerFactory() {
    @Override
    protected void postProcessContext(Context context) {
      ((StandardJarScanner) context.getJarScanner()).setScanManifest(false);
    }
  };
}
Run Code Online (Sandbox Code Playgroud)

解决方案3:传统独立Tomcat:

<Context>
  ...
  <JarScanner scanManifest="false"/>
  ...
</Context>
Run Code Online (Sandbox Code Playgroud)

参考:Jar扫描仪组件.

  • 但是由于这些是JDK的一部分,为什么要为它们扫描Maven存储库?禁用作品,但不应该不搜索它们中的那些jar吗? (3认同)

rus*_*tyx 8

只是为了改善Sundaraj的发现...完全禁用TLD扫描将破坏对 JSP / JSTL的支持。

问题在于类路径本身是可以的,只有Tomcat会额外扫描每个Jar 的清单文件,并且由于使用Maven,每个Jar都位于其自己的目录中,因此会生成无意义的路径(可能是从Eclipse运行?)。

因此,如果要继续将JSP与JSTL结合使用,则应仅禁用清单扫描。

对于Spring Boot 2.0,请将其添加到应用程序的配置中:

  @Bean
  public TomcatServletWebServerFactory tomcatFactory() {
    return new TomcatServletWebServerFactory() {
      @Override
      protected void postProcessContext(Context context) {
        ((StandardJarScanner) context.getJarScanner()).setScanManifest(false);
      }
    };
  }
Run Code Online (Sandbox Code Playgroud)