Maven项目中如何配置Spring Boot Devtools的依赖查找路径?
问题原因
- 你使用的Spring Boot 2.1.9.RELEASE内置的devtools存在已知的传递依赖路径解析bug:devtools的RestartClassLoader处理传递依赖时,会错误地将子依赖的jar包名拼接到父依赖的本地仓库目录下查找,而非按照子依赖自身的groupId、artifactId去对应目录寻址,才会出现从
~/.m2/repository/org/glassfish/jaxb/jaxb-runtime/2.3.1/路径下查找jaxb-api.jar的错误。 spring-boot:run和fat war的类加载逻辑存在本质差异:构建出的fat war内置了所有依赖,使用Spring Boot自带的LaunchedURLClassLoader从war包内部加载资源,不会涉及本地Maven仓库的路径解析;但spring-boot:run运行时会直接读取本地Maven仓库的依赖,走devtools的自定义类加载逻辑,因此会触发上述bug。- 你未在pom中显式声明devtools版本,默认会继承Spring Boot父pom对应版本的devtools,刚好命中上述bug。
解决方案
- 方案1:不需要使用devtools热重载功能的情况下,运行命令时直接禁用devtools即可,执行:
mvn spring-boot:run -Dspring-boot.run.excludeDevtools=true
即可完全避开devtools的类加载逻辑,使用Maven默认的依赖解析路径运行项目。 - 方案2:需要保留devtools功能的话,可直接在pom的dependencies节点中显式声明缺失的依赖,比如本例中的jaxb-api:
<dependency> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> <version>2.3.1</version> </dependency>
显式声明的依赖会被Maven优先加载,devtools会直接从该依赖对应的正确路径读取jar包,不会触发传递依赖的路径解析bug,同类缺失的依赖都可以用该方式处理。
- 方案3:调整spring-boot-maven-plugin配置,关闭devtools的独立线程启动器,使用标准Maven类加载逻辑:
<plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>2.1.9.RELEASE</version> <configuration> <useSeparateThreadLauncher>false</useSeparateThreadLauncher> </configuration> </plugin>
配置后再次执行mvn spring-boot:run即可正常解析所有依赖路径。
- 方案4:升级Spring Boot小版本到2.1.12.RELEASE及以上,该版本已经官方修复了devtools的传递依赖路径解析bug,升级后无需额外配置即可正常运行。
内容的提问来源于stack exchange,提问作者eoinmullan
相关产品推荐
相关产品推荐

