在 Spring Boot 中嵌入 tomcat 中禁用 Jar Scan 的 scanManifest

Posted

技术标签:

【中文标题】在 Spring Boot 中嵌入 tomcat 中禁用 Jar Scan 的 scanManifest【英文标题】:Disable scanManifest of Jar Scan in tomcat embed in spring boot 【发布时间】:2017-09-08 07:28:12 【问题描述】:

我在日志中收到一些警告,如下所示:

java.io.FileNotFoundException: C:\Users\user\.m2\repository\com\lowagie\itext\2.0.8\bcmail-jdk14-138.jar (O sistema não pode encontrar o arquivo especificado)
    at java.util.zip.ZipFile.open(Native Method) ~[na:1.8.0_121]
    at java.util.zip.ZipFile.<init>(ZipFile.java:219) ~[na:1.8.0_121]
    at java.util.zip.ZipFile.<init>(ZipFile.java:149) ~[na:1.8.0_121]
    at java.util.jar.JarFile.<init>(JarFile.java:166) ~[na:1.8.0_121]
    at java.util.jar.JarFile.<init>(JarFile.java:130) ~[na:1.8.0_121]
    at org.apache.tomcat.util.scan.JarFileUrlJar.<init>(JarFileUrlJar.java:60) ~[tomcat-embed-core-8.5.6.jar:8.5.6]
    at org.apache.tomcat.util.scan.JarFactory.newInstance(JarFactory.java:48) ~[tomcat-embed-core-8.5.6.jar:8.5.6]
    at org.apache.tomcat.util.scan.StandardJarScanner.process(StandardJarScanner.java:338) ~[tomcat-embed-core-8.5.6.jar:8.5.6]
    at org.apache.tomcat.util.scan.StandardJarScanner.scan(StandardJarScanner.java:288) ~[tomcat-embed-core-8.5.6.jar:8.5.6]
    at org.apache.jasper.servlet.TldScanner.scanJars(TldScanner.java:262) [tomcat-embed-jasper-8.5.6.jar:8.5.6]
    at org.apache.jasper.servlet.TldScanner.scan(TldScanner.java:104) [tomcat-embed-jasper-8.5.6.jar:8.5.6]
    at org.apache.jasper.servlet.JasperInitializer.onStartup(JasperInitializer.java:101) [tomcat-embed-jasper-8.5.6.jar:8.5.6]
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5178) [tomcat-embed-core-8.5.6.jar:8.5.6]
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) [tomcat-embed-core-8.5.6.jar:8.5.6]
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1403) [tomcat-embed-core-8.5.6.jar:8.5.6]
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1393) [tomcat-embed-core-8.5.6.jar:8.5.6]
    at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_121]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_121]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_121]
    at java.lang.Thread.run(Thread.java:745) [na:1.8.0_121]

在独立的 tomcat 中,我可以使用以下命令创建 context.xml

<Context>
  ...
  <JarScanner scanManifest="false"/>
  ...
</Context>

如何使用 Spring Boot 在 java 配置类中禁用清单文件 (https://tomcat.apache.org/tomcat-8.0-doc/config/jar-scanner.html) 的 JarScanner。

【问题讨论】:

【参考方案1】:

编辑:这个怎么样?

  @Bean
  public EmbeddedServletContainerFactory embeddedServletContainerFactory() 
    return new TomcatEmbeddedServletContainerFactory() 
      @Override
      protected void postProcessContext(Context context) 
        ((StandardJarScanner) context.getJarScanner()).setScanManifest(false);
      
    ;
  

【讨论】:

谢谢!我已将此行添加到我的应用程序类中,警告消失了。 我收到此错误Unable to start EmbeddedWebApplicationContext due to multiple EmbeddedServletContainerFactory beans : tomcatFactory,embeddedServletContainerFactory。我该如何解决? 查看 Spring Boot 2.X 的 rustyx 答案【参考方案2】:

现在可以通过属性控制:

# Comma-separated list of additional patterns that match jars to ignore for TLD scanning.    
server.tomcat.additional-tld-skip-patterns=*.jar

通过AFTER upgrade from Spring boot 1.2 to 1.5.2, FileNotFoundException during Tomcat 8.5 Startup

【讨论】:

设置此项将破坏 .JSP 支持,因为根本不会解析 TLD。 这不会破坏 .JSP 支持。它禁止使用清单文件来配置额外的扫描。您可以将*.jar 模式替换为给您带来麻烦的模式。例如在我的项目中,我使用server.tomcat.additional-tld-skip-patterns: jaxb-*.jar 如果我想要多个模式呢?这种事情有效:server.tomcat.additional-tld-skip-patterns=jaxb-api*.jar,txw2* 实际上这个解决方案关闭了对 TLD 的扫描,所以如果你的 jar 中有标签库,它将不会包含在你的运行时 @JJRoman 如果我保留 TLD 扫描标签库,你的替代解决方案是什么?【参考方案3】:

只是想改进 Oleg 关于 Spring Boot 1.x 的出色回答。

下面是 Spring Boot 2.0 (Tomcat 8.5) 对应的代码:

  @Bean
  public TomcatServletWebServerFactory tomcatFactory() 
    return new TomcatServletWebServerFactory() 
      @Override
      protected void postProcessContext(Context context) 
        ((StandardJarScanner) context.getJarScanner()).setScanManifest(false);
      
    ;
  

只需将其添加到应用程序的配置中即可。

【讨论】:

【参考方案4】:

与rustyx 建议的略有不同,基于this,因为我正在自定义我的执行器管理端口。

@Bean
public TomcatServletWebServerFactory containerFactory() 
    return new CustomTomcatServletWebServerFactory();


static final class CustomTomcatServletWebServerFactory
    extends TomcatServletWebServerFactory 

    @Override
    protected void postProcessContext(Context context) 
        ((StandardJarScanner) context.getJarScanner()).setScanManifest(false);
    


【讨论】:

以上是关于在 Spring Boot 中嵌入 tomcat 中禁用 Jar Scan 的 scanManifest的主要内容,如果未能解决你的问题,请参考以下文章

如何在 spring-boot 中拦截嵌入式 Tomcat 上的“全局”404

在 Spring Boot 中处理嵌入式 Tomcat 异常

在 spring-boot 中配置嵌入式 apache tomcat 内的“tomcat-server.xml”文件

使用 Spring Boot 中嵌入的 tomcat 进行远程调试或本地调试

无法在 Spring Boot 中启动嵌入式 Tomcat [重复]

在 Spring Boot 中嵌入 tomcat 中禁用 Jar Scan 的 scanManifest