如何让Maven Spring Boot忽略MANIFEST.MF中的Class-Path条目?
问题
我的Maven Spring Boot项目依赖的部分库,其META-INF/MANIFEST.MF文件包含Class-Path:条目——这是一种可追溯至90年代的老旧依赖管理方式,无法像Maven那样自动下载依赖,也不支持版本控制、发布或应用组装,如今Maven已能在后台更高效简便地处理这些工作。
但使用mvn spring-boot:run运行应用时,会出现如下警告:
WARN o.a.tomcat.util.scan.StandardJarScanner : Failed to scan [file: /home/service/.m2/repository/g/a/1.0/b.jar] from classloader hierarchy java.io.IOException: java.lang.reflect.InvocationTargetException at org.apache.tomcat.util.compat.Jre9Compat.jarFileNewInstance(Jre9Compat.java:209) ~[tomcat-embed-core-9.0.45.jar:9.0.45] at org.apache.tomcat.util.scan.JarFileUrlJar.<init>(JarFileUrlJar.java:65) ~[tomcat-embed-core-9.0.45.jar:9.0.45] … at com.cat.web.SpringWebAppStarter.main(SpringWebAppStarter.java:35) ~[classes/:na] Caused by: java.lang.reflect.InvocationTargetException: null at java.base/jdk.internal.reflect.GeneratedConstructorAccessor20.newInstance(Unknown Source) ~[na:na] ... 46 common frames omitted Caused by: java.nio.file.NoSuchFileException: /home/service/.m2/repository/g/a/1.0/b.jar
具体案例中,依赖库g:a.jar(组名和名称已简化)的MANIFEST内容如下:
Class-Path: b.jar
该b.jar是可选库,我的应用实际并未使用它。
如何配置Maven或Spring Boot,使其仅通过自身管理依赖,完全忽略依赖库MANIFEST文件中的Class-Path条目?
解决方案
方法1:禁用Tomcat的Jar扫描功能
Spring Boot内嵌Tomcat的JarScanner会自动扫描MANIFEST文件中的Class-Path条目,我们可以通过配置直接禁用该行为:
方式A:通过配置文件
在application.properties中添加:
server.tomcat.jar-scanning=disabled server.tomcat.additional-tld-skip-patterns=*.jar
或者在application.yml中添加:
server: tomcat: jar-scanning: disabled additional-tld-skip-patterns: "*.jar"
方式B:通过Java配置类
创建配置类自定义Tomcat容器:
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.server.WebServerFactoryCustomizer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class TomcatCustomConfig { @Bean public WebServerFactoryCustomizer<TomcatServletWebServerFactory> tomcatCustomizer() { return factory -> factory.getTomcatContext().setJarScanner(null); } }
方法2:修复有问题的依赖库
如果g:a.jar的MANIFEST中Class-Path是多余配置,可以尝试:
- 检查该库是否有更新版本,新版本可能已移除老旧的
Class-Path条目; - 若无法更新,使用
maven-shade-plugin重新打包该库,移除MANIFEST中的Class-Path:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.4.1</version> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <filters> <filter> <artifact>g:a</artifact> <includes> <include>**/*</include> </includes> <excludes> <exclude>META-INF/MANIFEST.MF</exclude> </excludes> </filter> </filters> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <!-- 生成不带Class-Path的默认MANIFEST --> </transformer> </transformers> </configuration> </execution> </executions> </plugin>
方法3:通过Spring Boot Maven插件添加JVM参数
在pom.xml的spring-boot-maven-plugin中配置JVM参数,让Tomcat跳过所有Jar的扫描:
<plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <jvmArguments>-Dtomcat.util.scan.StandardJarScanFilter.jarsToSkip=*.jar</jvmArguments> </configuration> </plugin>
也可以直接在运行命令中临时添加参数:
mvn spring-boot:run -Dtomcat.util.scan.StandardJarScanFilter.jarsToSkip=*.jar
内容的提问来源于stack exchange,提问作者Joe DiNottra
相关产品推荐
相关产品推荐

