SpringBoot集成OpenAPI后用shadow插件打胖包启动报ApplicationContextException
问题根因
该报错不是依赖冲突导致,是shadow插件打包时的默认资源合并策略存在缺陷:SpringBoot、springdoc-openapi都在META-INF路径下存放了自动配置元数据(包括spring.factories、AutoConfiguration.imports等文件),shadow打包时会直接覆盖同名文件,仅保留最后加载的依赖中的对应文件内容,导致SpringBoot的ServletWebServerFactory自动配置类未被扫描加载,最终抛出缺少对应bean的错误。
本地运行、gradlew bootRun启动时直接使用项目原始classpath,所有依赖的配置文件独立存在不会被覆盖,因此运行正常;移除springdoc-openapi-ui依赖后不存在同名配置文件覆盖问题,因此打包后也可正常启动。
解决方案
- 方案一:修改shadow插件配置,新增配置文件合并规则
在build.gradle中添加如下shadowJar配置:
shadowJar { // 合并所有SPI服务配置文件 mergeServiceFiles() // 追加合并SpringBoot自动配置相关文件,避免覆盖 append 'META-INF/spring.factories' append 'META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports' // 剔除签名文件避免jar包校验失败 exclude 'META-INF/*.SF', 'META-INF/*.DSA', 'META-INF/*.RSA' manifest { attributes 'Main-Class': 'org.springframework.boot.loader.JarLauncher' attributes 'Start-Class': 'com.example.Application' } }
注意:此处Main-Class需设置为SpringBoot的JarLauncher而非业务主类,确保SpringBoot的类加载机制正常生效。
- 方案二:强制指定Web应用类型
若调整打包配置后仍存在问题,可在application.properties中添加配置强制指定web容器类型:
spring.main.web-application-type=servlet
也可在启动类中通过代码指定:
@SpringBootApplication public class Application { public static void main(String[] args) { new SpringApplicationBuilder(Application.class) .web(WebApplicationType.SERVLET) .run(args); } }
调整完成后重新执行gradlew shadow打包,启动jar包即可正常运行。
内容的提问来源于stack exchange,提问作者Shalabh Raj
相关产品推荐
相关产品推荐

