遇到 Plugin 'org.springframework.boot:spring-boot-maven-plugin' not found 这个报错,多半是刚刚开始用 Spring Boot + Maven 做项目,或者是换了台电脑、拉了个新仓库想在本地跑起来的时候。这个错说直白点就是 Maven 找不到 spring-boot-maven-plugin 这个插件,但它其实不是真的“没有这个插件”,而是 Maven 在解析项目时没有找到插件所在的依赖源,或者你根本还没把 Spring Boot 的父工程声明到 pom.xml 里。
我最早碰到这个错是在一个接手的老项目里,当时第一反应是去检查 settings.xml 的镜像仓库,结果折腾了半天才发现是 IDEA 里 Maven 的配置指向了内置的打包版本,本地仓库路径也不对,导致插件根本下载不下来。这篇文章就结合我自己的排查过程,把几个最典型的成因和解决办法整理一下,包含完整的排查链路,希望能帮你少走弯路。
1. 报错的直接原因和它背后真正的含义
先看报错信息本身:Plugin 'org.springframework.boot:spring-boot-maven-plugin' not found。如果只是看这一行,很容易误以为是某个依赖没有引入,然后跑去 pom.xml 里加 spring-boot-maven-plugin 依赖,结果发现加完还是报错。实际上 Maven 插件报 not found,通常有下面几种可能,它们指向的修复方向完全不同。
1.1 你的项目根本就没继承 Spring Boot 父工程
这个是新手最容易踩的坑。spring-boot-maven-plugin 是一个 Maven 插件,它的 groupId 是 org.springframework.boot,artifactId 是 spring-boot-maven-plugin。Maven 插件本身不像普通依赖那样声明在 <dependencies> 里,而是声明在 <build><plugins> 里。大多数情况下,你会在 pom.xml 里这样写:
xml复制<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.18</version>
<relativePath/>
</parent>
然后在 <build> 声明插件的时候,连 <version> 都不用写:
xml复制<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
如果项目没有继承 Spring Boot 的 spring-boot-starter-parent,也没有通过 <dependencyManagement> 引入 Spring Boot 的 BOM,那么 Maven 就不知道该用哪个版本的 spring-boot-maven-plugin,于是就会报 not found。
这种情况在什么场景下最容易出现?一是你手动在网上找了一段 pom.xml 配置,只贴了 <build> 那一段,忘了把 <parent> 也贴进去;二是你之前用的是别的构建方式,比如 Gradle,现在切到 Maven,对两者的配置差异不熟悉;三是项目是一个多模块工程,你在子模块里单独配置了插件,但父模块没有做统一管理。
1.2 本地 Maven 仓库里确实没有这个插件包
这种情况也很常见,尤其是刚配好 Maven 环境的时候。Maven 在构建时会把插件从远程仓库下载到本地仓库,默认路径是用户目录下的 .m2/repository。如果你的本地仓库是第一次使用,或者之前从未构建过 Spring Boot 项目,那么 spring-boot-maven-plugin 对应的 jar 包就还没被下载下来。
这时候你会看到一个额外的提示,比如:
code复制The POM for org.springframework.boot:spring-boot-maven-plugin:jar:2.7.18 is missing, no dependency information available
或者构建日志里出现 Could not resolve dependencies 之类的字样。这种情况的原因可能是网络受限、远程仓库访问不了,或者 Maven 的镜像仓库配置有问题,导致插件下载失败,最终 Maven 只能认为这个插件“not found”。
1.3 IDEA 的 Maven 配置阴差阳错指向了内置仓库
用 IntelliJ IDEA 开发的同学,很多人会遇到一个很诡异的现象:命令行里直接执行 mvn clean package 一切正常,但 IDEA 里一点刷新按钮就报 not found。这种情况九成是 IDEA 里配置的 Maven home path、settings file、local repository 三者之间不匹配导致的。
比如你在系统里装了自己的 Maven,配好了阿里云镜像,本地仓库在 D:\maven-repo。但 IDEA 默认使用内置的 Maven(Bundled 版本),settings file 指向的是 IDEA 自己生成的 settings.xml,local repository 也因此指向了一个你从未使用过的目录。IDEA 会按照那套配置去 .m2/repository 里找插件,找了一圈发现没有 spring-boot-maven-plugin,然后报错。
前端工具链里经常说“环境问题”,后端 Java 开发里环境问题最典型的就是这种:命令行能过,IDE 过不了,十有八九是 IDE 和命令行走的不是同一套配置。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 按优先级排查的三个关键目录和配置文件
处理这类问题,我个人的习惯是先从“Maven 到底去哪找插件”入手。你可以把 Maven 的查找过程理解成快递员送件:他必须先知道收货地址(本地仓库路径),知道用哪个快递公司(settings.xml 里的 mirror),然后找到对应楼栋的房间号(本地仓库目录下对应的 groupId/artifactId/version 目录),最后才能把包裹(插件 jar 包)放到正确的位置。任何一个环节出错,结果都是“查无此件”。
2.1 先确认你本地 Maven 仓库里有没有这个插件
先找到 Maven 本地仓库的物理路径。不确定的话,在命令行执行:
bash复制mvn help:evaluate -Dexpression=settings.localRepository -q -DforceStdout
这个命令会直接输出你当前 Maven 配置下的本地仓库路径。拿到路径之后,去看这个目录:
code复制/org/springframework/boot/spring-boot-maven-plugin/
如果这个目录底下能找到对应版本的子目录,并且里面有 .jar 和 .pom 文件,说明插件文件本身是有的。找不到的话,就说明插件从未下载成功,或者根本还没开始下载。这时候再看 settings.xml 的 mirror 配置。
我之前在一台新电脑上排查时,跑了上面的命令,输出的路径是 C:/Users/xxx/.m2/repository,然后我去 org/springframework/boot 目录下看了下,发现只有 spring-boot-starter-parent 没有 spring-boot-maven-plugin,说明依赖和插件下载了一半就中断了。后来全量清理重新构建,问题才彻底解决。
2.2 settings.xml 里最容易出问题的 mirror 配置
Maven 的 settings.xml 通常位于 %MAVEN_HOME%/conf/settings.xml 或用户目录下的 .m2/settings.xml。国内开发者基本都会配阿里云镜像,用镜像的原因很简单:中央仓库的下载速度在国内实在太折磨人了,小插件还好,一个包含几百个依赖的 Spring Boot 项目用中央仓库构建一次,等得让人怀疑人生。
这里有一个非常隐蔽的坑:阿里云镜像有一个仓库分组,叫 public,它同时聚合了 central 和 jcenter。如果你在 settings.xml 里配置的 mirrorOf 是 *,所有请求都会走镜像,这本身没毛病。但如果镜像地址配错了,比如复制配置的时候多了一个空格或者少了斜杠,Maven 连不上镜像仓库,就会报各种奇怪的错,其中就包括插件 not found。
一个相对稳妥的阿里云镜像配置长这样:
xml复制<mirror>
<id>aliyunmaven</id>
<mirrorOf>*</mirrorOf>
<name>阿里云公共仓库</name>
<url>https://maven.aliyun.com/repository/public</url>
</mirror>
注意 mirrorOf 这里用的是 *,表示所有仓库请求都走这个镜像。如果只是希望中央仓库走镜像,其他仓库正常访问,可以写成 <mirrorOf>central</mirrorOf>。但建议你先把这个问题修好再考虑精细化配置,不要一开始就搞太复杂。
2.3 IDEA 里 Maven 配置检查的三板斧
如果你习惯用 IDEA,打开 Settings -> Build, Execution, Deployment -> Build Tools -> Maven,检查这三个地方:
第一,Maven home path。建议选择你本地安装的 Maven 路径,而不是 IDEA 自带的 bundled Maven。第二,User settings file。这里有个大坑,IDEA 默认勾选了 Override,但指向的 settings.xml 可能不是你命令行用的那个,建议手动选定你实际使用的配置文件。勾选 Override 后,旁边会出现一个文件夹图标,点击可以重新选择。第三,Local repository。正常情况下它会根据 settings.xml 自动识别,但如果你之前手动指定过,就会覆盖掉 settings.xml 里的路径。这里一定要确认它指向的目录,和你在命令行里查到的一致。
我之前就遇到过这种问题:命令行构建好好的,IDEA 刷新 Maven 项目后报错,打开配置一看,Local repository 显示的是 C:\Users\xxx\.m2\repository,但我的 settings.xml 里明明把本地仓库指定到了 D:\tools\maven-repo。IDEA 里的手动配置优先级更高,所以它一直在错误的位置找插件,找了半天什么都没有,自然就报 not found 了。
3. 用最可靠的方案把插件完整拉取下来
排查完环境配置后,接下来就是实际操作。这里我不推荐直接在 pom.xml 里给插件加一个 <version> 就完事,因为如果父工程都没配对,加了版本号也掩盖不了根本问题。正确顺序是:先确保项目继承关系正确,再检查 Maven 能正常下载插件,最后刷新构建。
3.1 确保 pom.xml 声明了 Spring Boot 父工程或 BOM 导入
如果你是在一个标准 Spring Boot 项目里工作,pom.xml 的 project 标签内第一件重要的事就是声明 <parent>。Spring Boot 官方文档推荐的做法是继承 spring-boot-starter-parent:
xml复制<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.18</version>
<relativePath/>
</parent>
如果你所在的团队不允许继承这个父工程,比如公司内部已经统一了自己的 parent,那么可以在 <dependencyManagement> 部分引入 Spring Boot 的 BOM,效果类似:
xml复制<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.7.18</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
这么做本质上就是让 Spring Boot 帮你去管理那些常用依赖的版本号,其中就包括 spring-boot-maven-plugin 的版本。有了这个版本管理,<build><plugins> 里的插件声明才不用写 <version>。插件版本管理是通过父工程里 <pluginManagement> 实现的,spring-boot-starter-parent 内部已经对 spring-boot-maven-plugin 做了版本固定,所以项目里不需要重复声明版本。
3.2 修改 pom.xml 后执行一次强制重新下载
如果你确认 pom.xml 的配置没问题,只是本地仓库里确实还没有这个插件,可以执行一次 Maven 的强制刷新。在 IDEA 右侧的 Maven 面板点刷新按钮有时不够彻底,更推荐直接在命令行执行:
bash复制mvn clean compile
或者跳过测试直接打包:
bash复制mvn clean package -DskipTests
如果你用的是 IDEA 内置的 Maven,不想切到命令行,可以在 IDEA 的 Maven 工具窗口里点击生命周期里的 clean 和 compile。但有一个前提:IDEA 里的 Maven 配置必须先对齐,否则你还是会重复踩坑。
首次执行构建时,Maven 会去远程仓库下载一堆依赖,日志里会看到很多 Downloading from aliyunmaven 之类的输出。耐心等它跑完。如果卡住不动,或者报连接超时,多半是镜像仓库不可达或者网络受限。这时候可以试试换一个镜像地址,比如华为云镜像:
xml复制<mirror>
<id>huaweicloud</id>
<mirrorOf>*</mirrorOf>
<url>https://repo.huaweicloud.com/repository/maven/</url>
</mirror>
还有一个冷门但很有效的方式:手动下载插件包丢进本地仓库。先去 Spring 官方仓库或阿里云镜像上找到 spring-boot-maven-plugin 对应版本的 pom 和 jar,下载后按目录层级放到本地仓库里。这个方法只能用来应急,比如你内网环境隔离、没法访问外网镜像,但公司内部 Nexus 上恰好没有你需要的那版插件,手动物理投放才能继续往下走。
3.3 针对多模块项目的额外检查点
如果你处理的是一个多模块项目,比如有 common、admin、api 这些子模块,那么每个子模块的 pom.xml 里不需要都声明 spring-boot-maven-plugin。只有真正需要打包成可执行 jar 的那个模块才需要这个插件,通常是启动类所在的模块。父 pom.xml 里则可以使用 <pluginManagement> 对插件版本做统一管理:
xml复制<pluginManagement>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</pluginManagement>
然后在需要的子模块里引用:
xml复制<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
如果你是子模块的 pom 里声明了插件但父 pom 没做管理,同时子模块又没继承 Spring Boot 父工程,那这个子模块单独构建时就很容易出现 not found。这种情况不算少见,尤其是一个团队里有人负责配置父 pom,有人负责写子模块,协作的时候容易漏掉。
4. 一次完整的真实排查过程:从报错到修复的分步记录
前面给的都是分点知识,这里我把一次真实排查过程完整复盘一遍,从报错现场到最终修复,过程呈现出来比单点答案更有参考意义。
4.1 现场还原与初步判断
一个同事拿了个项目过来找我,说在 IDEA 里跑不起来,报错信息是:
code复制Plugin 'org.springframework.boot:spring-boot-maven-plugin' not found
我第一件事不是去翻 pom.xml,而是先看了一眼 IDEA 的 Maven 配置。发现 Maven home path 是 IDEA 自带的 bundled Maven,User settings file 指向了 C 盘用户目录下的 .m2/settings.xml,但我记得他电脑上装了自己的 Maven,而且配置过国内镜像。把他的 IDEA 配置切回自己安装的 Maven 路径后,项目一下子就能正常 import 了。
这个案例看起来简单,但它说明了一个很核心的问题:报错信息只负责告诉你“什么东西找不到”,不会直接告诉你“应该去哪里找”。当你顺着 Maven 的查找路径去排查,问题往往就出现在路径本身。
4.2 命令行构建暴露出来的隐藏坑
另一个案例来自我自己的一个开源项目。当时我在命令行执行 mvn clean package -DskipTests,构建很顺利,jar 也打出来了。但把项目切换到另一个分支后,重新构建就报 not found。我自然想到是分支里的 pom.xml 和原来的不一样,于是去查差异,发现新分支里的 pom.xml 把 Spring Boot 的版本从 2.7.18 升到了 3.1.5,但这个分支没有同步更新父工程的 relativePath,导致父 pom 的解析失败。
这里插一个知识点:<relativePath/> 设置为空,表示不想从本地相对路径解析父 pom,而是希望从 Maven 仓库下载。如果你的项目里把 relativePath 指向了一个不存在的本地路径,Maven 解析父 pom 时也会失败。父 pom 都解析不了,后续的插件版本管理自然就失效了,插件也就变成 not found。
4.3 清理本地仓库破局
还有一个案例更刁钻。本地仓库里有 spring-boot-maven-plugin 的目录,但目录里只有一个 .lastUpdated 结尾的文件,没有实际的 jar 包。这个 .lastUpdated 文件是 Maven 下载失败的标志,它记录了上次下载失败的时间点和原因。Maven 在之后重新构建时,会先看到这个标记,如果它认为距离上次失败的时间太短(默认更新策略导致),就可能直接跳过下载,报 not found。
解决方式也很直接:把 spring-boot-maven-plugin 所在目录整个删掉,或者干脆把 _remote.repositories 和 .lastUpdated 相关的残留文件清理干净,然后重新执行构建。Maven 看到目录里啥都没有了,就会老老实实再去拉一次完整的插件。用 IDEA 刷新依赖时如果老是失败,也可以用这个思路:手动删掉有问题的本地仓库缓存,强制让 Maven 重新下载。
5. 再深挖一层:spring-boot-maven-plugin 的职责和实际应用
报错解决之后,很多人会把插件的事抛到脑后,直接打包跑应用去了。但我建议还是稍微了解一下这个插件是干嘛的,能帮你少踩之后的坑,特别是在打包、部署、生成镜像这些环节上。
5.1 它到底把什么打包进了最终产物
spring-boot-maven-plugin 的核心任务是生成 Spring Boot 应用的可执行 jar。这个 jar 不同于普通 Maven 打的 jar,它是一个 fat jar,里面不只是你项目的 class 文件,还包括了所有第三方依赖、内嵌的 Tomcat 容器、Spring Boot 的启动器。启动时通过 java -jar xxx.jar 就能把内置 Tomcat 拉起来,整个应用独立运行,不需要外部再部署一个 Tomcat 容器。
这就解释了为什么普通 Spring Boot 项目打包时,如果你不用这个插件,打出来的 jar 会非常小,而且执行 java -jar 的时候会报“没有主清单属性”。这个插件在打包过程中会把 Main-Class 和 Start-Class 写进 jar 的 MANIFEST.MF 文件里,并指导 Maven 生成 BOOT-INF/lib、BOOT-INF/classes 的标准目录结构。没有这些,Spring Boot 应用根本无法以 java -jar 的方式启动。
5.2 插件的高级用法:跳过重新打包与生成镜像信息
spring-boot-maven-plugin 的集成除了基本的打包功能,还提供了一些可配置的目标参数。比如在模块化开发中,如果子模块只是被别的模块依赖,不需要自己打成可执行 jar,可以在该模块的插件配置里加上:
xml复制<configuration>
<skip>true</skip>
</configuration>
再比如你想在构建时顺便生成 Docker 镜像元数据,可以用 build-image 目标。Spring Boot 2.3 之后,插件内置了云原生构建包(Cloud Native Buildpacks)的支持,通过配置 image 标签的 name 属性,执行 mvn spring-boot:build-image 就能直接构建出一个包含应用运行环境的 OCI 镜像。但这也意味着你本地需要安装 Docker,并且网络要能访问 buildpacks 相关仓库,国内环境下这一步经常因为网络问题失败。
对这些高级用法,一个很值得肯定的经验是:先把基础构建跑通,再考虑这些进阶配置。否则插件本身还报 not found 的时候,去调 skip 或 image 标签没有任何意义,反而会让问题复杂化。
5.3 常见版本兼容性问题
Spring Boot 2.x 和 3.x 之间,spring-boot-maven-plugin 的使用方式有细微差异,主要体现在 JDK 版本要求和默认的构建参数上。比如 Spring Boot 3.x 要求 JDK 17 及以上,如果你本地是 JDK 8,执行插件就会报 UnsupportedClassVersionError,这说明插件本身能找到,但运行环境不兼容。这类报错不能再用“插件 not found”的思路去修,而是要先升级 JDK 或者调整 Spring Boot 版本。
排查的时候记得看一眼 IDEA 里 Project Structure 配置的 SDK 和 Maven 的 Java 版本设置。一个常见的低级失误是:pom.xml 里的 java.version 写了 17,但 IDEA 里 Project SDK 还是 1.8。结果编译阶段没报错,一跑到插件阶段,插件内部用的类是 JDK 17 编译的,在 JDK 8 上直接运行失败。Maven 的 JAVA_HOME 和 IDEA 的 SDK 如果不一致,也会出现类似问题。这个点虽然是版本兼容类的,但它的表象经常和 not found 混在一起出现,特别是你删掉本地仓库重新下载后仍然失败时,更要检查一下环境变量。
6. 解决之后的收尾动作和几条实操建议
问题修复只是第一步,关键是要能稳住,不要每次都靠排查来救火。这里整理一下我每次搭完 Spring Boot 项目之后会做的几件小事,权重很高。
6.1 验证最终构建产物能不能正常启动
很多开发者的习惯是看到 BUILD SUCCESS 就收工,但插件问题会导致一种情况:构建日志全绿,jar 也生成了,但拿到服务器上 java -jar 跑不起来。这时候再回去看日志,会发现原来打出来的不是可执行 fat jar。所以修完 not found 之后,最好多走一步验证,直接在本地:
bash复制java -jar target/xxx.jar
能起来,说明打包配置真的对了。起不来,看它报什么错,常见的就是“no main manifest attribute”,这个报错基本可以断定 spring-boot-maven-plugin 没有正确参与打包,或者打包目标是普通 jar 而不是 repackage 后的产物。Spring Boot 插件的 repackage goal 是在 package 阶段执行的,如果你的生命周期里没有正确绑定,也会出现这个情况。
6.2 别让 IDEA 和命令行长期保持两套配置
这个问题值得反复强调。我现在每到一个新环境,第一件事就是把 IDEA 的 Maven 配置手动检查一遍,确保和系统里的 Maven 配置完全一致。具体动作就是:自己安装 Maven,使用同一份 settings.xml,本地仓库也用同一个目录。这样无论你在命令行操作还是 IDEA 里刷新,看到的依赖状态都是一样的,排查环境问题时思路也能保持单一。
如果你的团队里多人协作,建议把 Maven 的安装路径、JDK 版本、settings.xml 路径记到项目的 README 里。很多人忽略了这个细节,导致新入职的同事上来第一件事就是各种 not found 报错,不仅浪费时间,还很容易被拉进“代码有问题”的错误方向里。
6.3 有没有必要手动指定插件版本号
有一个小争论顺便聊一下。有的开发者在 <build><plugins> 里手写了插件的 <version>,像这样:
xml复制<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.7.18</version>
</plugin>
这样做的好处是,即使父工程没有做插件版本管理,Maven 也能根据显式版本号去解析和下载插件。坏处是,如果 Spring Boot 版本升级了,而这里忘记同步,版本号就会不一致,可能导致一些很难察觉的运行时行为差异。个人建议是优先依赖父工程的插件版本管理,不显式写版本号。只在纯工具类项目或者确实没有引入 Spring Boot 父工程的情况下,才建议手写版本号。
6.4 清理已知坏缓存,把构建环境还原成“干净状态”
最后收个尾。排查了半天,如果你确认 pom.xml、settings.xml、IDEA 配置都没问题,但 plugin 还是 not found,那基本可以断定本地 Maven 仓库缓存出问题了。这种时候不要犹豫,直接执行两段式清理。
第一段,删掉特定插件的缓存目录。因为全量删除 .m2/repository 代价太高,很多依赖重新下载耗时很久。可以先只删出问题的插件目录:
bash复制rm -rf ~/.m2/repository/org/springframework/boot/spring-boot-maven-plugin
如果删完重试还是不行,再考虑用 Maven 的 UPDATe 策略强制重新下载:
bash复制mvn clean install -U
-U 参数的含义是强制更新快照和插件,它的官方全称是 --update-snapshots。加上这个参数,Maven 会忽略 .lastUpdated 标记,主动重新拉取远程仓库中的最新版本。这个参数在排查各种“本地缓存坏了导致找不到依赖/插件”的问题时,是最常用的救命开关。
如果上面这些操作都做完了,还出现 not found,那就需要再往回走一步,检查网络层面的限制。比如你是不是在公司内网、防火墙是不是禁止了对外部仓库的访问、你配置的镜像仓库是不是内部某个 Nexus 地址,这些因素最终都会表现为“下载不下来”,而“下载不下来”在 Maven 这里通常就会被翻译成“XXX not found”。这种信息误差真的普遍存在,所以排查到最后,能够静下心沿着“配置文件路径、本地仓库缓存、网络与镜像”这三个维度逐一过一遍,往往比一上来就改 pom.xml 更高效、更对症。
