我升级 Spring 启动从1.2.0升级到 1.5.2 。
升级后,Tomcat 8.5 在启动期间抛出 FileNotFoundException 。
以下是 这些例外中的一个,它会抛出超过~10个类似的例外。
我不知道这些罐子的目的,换句话说,我没有在 pom.xml中为这些罐子添加<dependency>
。
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)
任何帮助都将不胜感激。
答案 0 :(得分:25)
<强>根本原因:强>
根据 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(默认情况下已禁用)
所有扩展程序均可通过配置进行控制。
解决方案1:特定于Spring Boot。
我们可以禁用此jar扫描。
我通过在application-xxx.properties文件中添加以下属性来禁用它。此属性为Spring Boot specific。
# Comma-separated list of additional patterns that match jars to ignore for TLD scanning.
server.tomcat.additional-tld-skip-patterns=*.jar
您可以在Tomcat中找到类似的属性 here。
这些属性可用于配置传统 tomcat(非 -spring启动)应用程序。
解决方案2:特定于春季
您可以为清单文件禁用JarScanner,如下所示。
@Bean
public EmbeddedServletContainerFactory embeddedServletContainerFactory() {
return new TomcatEmbeddedServletContainerFactory() {
@Override
protected void postProcessContext(Context context) {
((StandardJarScanner) context.getJarScanner()).setScanManifest(false);
}
};
}
解决方案3:传统的独立Tomcat:
<Context>
...
<JarScanner scanManifest="false"/>
...
</Context>
答案 1 :(得分:6)
只是为了改善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);
}
};
}
答案 2 :(得分:1)
JarScannerFactory loaded StandardJarScanner,我们需要配置here,因此(对于Spring Boot 2.1.8),它也可以工作。
import org.apache.tomcat.JarScanner;
import org.apache.tomcat.util.scan.StandardJarScanner;
import org.springframework.boot.web.servlet.ServletContextInitializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class WebContextConfiguration {
@Bean
public ServletContextInitializer servletContextInitializer() {
return context -> context.setAttribute(
JarScanner.class.getName(),
new StandardJarScanner() {{
setScanManifest(false);
}}
);
}
}