Maven使用总结
Maven仓库配置
参考博客:https://www.cnblogs.com/chanshuyi/p/quick-start-of-maven-pull.html
依赖管理
依赖声明
<dependency> 标签的核心是「坐标(groupId/artifactId/version)+ 作用域(scope)」,掌握以下关键点即可应对 99% 的场景:
- 必选属性:三个坐标唯一标识依赖,版本建议固定;
- 核心可选属性:
scope控制依赖生效阶段,exclusions解决冲突,optional控制传递性; - 特殊场景:
classifier区分同版本变体,type="pom"引入 BOM; - 避坑:少用
system作用域,优先用 BOM 统一版本。
scope:依赖作用域
控制依赖在 Maven 构建生命周期(编译、测试、打包、运行)中的可见性,同时影响依赖传递性。
| 作用域 | 编译期 | 测试期 | 运行期 | 打包(最终产物) | 依赖传递性 | 核心说明 |
|---|---|---|---|---|---|---|
compile |
✅ | ✅ | ✅ | ✅ | ✅ | 默认值,适用于主代码,全程有效(如业务核心依赖) |
test |
❌ | ✅ | ❌ | ❌ | ❌ | 仅测试阶段生效(如 JUnit、TestNG) |
provided |
✅ | ✅ | ❌ | ❌ | ❌ | 运行时由容器 / 环境提供(如 Servlet API、JDK),避免打包冲突 |
runtime |
❌ | ✅ | ✅ | ✅ | ✅ | 仅运行 / 测试时需要,编译不需要(如 JDBC 驱动、MySQL 连接器) |
system |
✅ | ✅ | ✅ | ❌ | ❌ | 系统依赖(本地 jar),需配合systemPath,不推荐(建议安装到本地仓库) |
import |
- | - | - | - | - | 仅用于<dependencyManagement>,导入 BOM 的版本信息(仅支持 pom 类型依赖) |
不同 scope 的典型使用场景:
<dependencies>
<!-- compile(默认):业务核心依赖 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson2</artifactId>
<version>2.0.45</version>
</dependency>
<!-- test:仅测试用 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<!-- provided:容器提供(如Tomcat提供Servlet API) -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<!-- runtime:仅运行/测试需要(编译不需要) -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
<scope>runtime</scope>
</dependency>
</dependencies>
type:依赖类型
指定依赖的打包类型,默认值为jar,常见类型如下:
| 类型 | 作用 | 示例场景 |
|---|---|---|
jar |
普通 Java 包(默认) | 绝大部分第三方库(如 fastjson2) |
pom |
POM 文件(用于 BOM、父模块依赖) | 引入 Spring Boot BOM、自定义 BOM |
war |
Web 应用包 | 依赖其他 WAR 包(极少用) |
ejb |
EJB 组件包 | 企业级 Java 组件 |
maven-plugin |
Maven 插件包 | 自定义 Maven 插件依赖 |
示例:引入 POM 类型的 BOM
<dependencyManagement>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.7.15</version>
<type>pom</type> <!-- 类型为pom -->
<scope>import</scope>
</dependency>
</dependencyManagement>
classifier:分类器
用于区分同一版本但不同变体的依赖(如不同 JDK 版本、不同环境的包),需配合type使用,常见场景:
- 区分 JDK 版本(如
jdk8、jdk11); - 区分源码包(
sources)、文档包(javadoc); - 区分操作系统包(如
linux-x86_64、windows-x86)。
optional:可选依赖
控制依赖的传递性,默认值为false:
optional="true":当前依赖不会传递给下游项目(下游需显式声明才会引入);optional="false":依赖会正常传递(默认行为)。
示例:可选依赖(避免下游自动引入)
<!-- 自研组件:可选依赖fastjson2,下游需显式声明才会引入 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson2</artifactId>
<version>2.0.45</version>
<optional>true</optional> <!-- 可选依赖 -->
</dependency>
exclusions:排除依赖传递
解决依赖冲突的核心手段,用于排除当前依赖传递引入的不需要的依赖(无需指定版本)。
systemPath:系统依赖路径
仅用于scope="system"的场景,指定本地文件系统中的依赖路径(绝对路径 / 相对路径),不推荐使用(易导致环境不一致)。
依赖传递性规则
Maven 依赖会自动传递(如 A 依赖 B,B 依赖 C,则 A 会间接依赖 C),传递性受以下因素影响:
scope:仅compile/runtime作用域的依赖会传递,test/provided/system不会;optional:optional="true"的依赖不会传递;exclusions:显式排除的依赖不会传递;- 版本冲突:Maven 会按「最短路径」「声明优先」规则选择版本(可通过
dependencyManagement覆盖)。
MVN工具使用
清理项目并重新安装所有依赖
mvn clean install
-U 参数会强制更新所有 SNAPSHOT 版本的依赖
mvn clean install -U
查看项目的依赖树: mvn dependency:tree
mvn archetype
使用Maven创建新项目
mvn archetype:generate -DgroupId=com.example -DartifactId=my-app -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
更新项目中的依赖版本
mvn versions:use-latest-releases
解析项目的所有依赖。强制更新快照版本的依赖,确保下载最新的依赖项,此命令来自插件maven-dependency-plugin
mvn dependency:resolve -U
常见问题与最佳实践
生成源码jar包 maven-source-plugin
https://maven.apache.org/plugins/maven-source-plugin/
此插件用于生成源码jar包:mvn source:jar
<project>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.1</version>
<executions>
<execution>
<id>attach-sources</id>
<phase>verify</phase>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
...
</project>
maven-jar-plugin 打jar包
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>com.example.MainClass</mainClass> <!-- 替换为你的主类 -->
</manifest>
</archive>
</configuration>
</plugin>
flatten-maven-plugin 版本管理 revision
插件定义好之后,在进行项目打包时,可以替换revision公共的版本号
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>flatten-maven-plugin</artifactId>
<version>1.1.0</version>
<configuration>
<updatePomFile>true</updatePomFile>
<flattenMode>resolveCiFriendliesOnly</flattenMode>
</configuration>
<executions>
<execution>
<id>flatten</id>
<phase>process-resources</phase>
<goals>
<goal>flatten</goal>
</goals>
</execution>
<execution>
<id>flatten.clean</id>
<phase>clean</phase>
<goals>
<goal>clean</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
问题1:${revision}无法被替换成真实的版本号
flatten-maven-plugin插件需要的maven版本,要3.5以上
versions-maven-plugin
mvn -N versions:update-child-modules 替换子模块版本,直接改代码
BOM
https://stackoverflow.com/questions/63033892/how-to-properly-use-maven-bom-s
用于统一管理依赖
BOM 本身不包含实际依赖,仅通过 <dependencyManagement> 标签声明依赖的版本、scope 等元信息。当其他项目引入 BOM 后,在 <dependencies> 中引用 BOM 中声明的依赖时,无需指定版本号,Maven 会自动从 BOM 中继承版本,实现版本统一管控。
核心特点:
- 版本统一:所有引入 BOM 的项目共用一套版本规则;
- 解耦版本与依赖:依赖的使用和版本管理分离;
- 解决冲突:优先使用 BOM 中声明的版本,避免依赖传递导致的版本不一致。
通过 <dependencyManagement> 引入 BOM(注意:BOM 必须放在 <dependencyManagement> 中,且 type 为pom、scope 为import)。
<!-- 依赖版本管理:引入BOM -->
<dependencyManagement>
<dependencies>
<!-- Spring Boot BOM -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.7.15</version> <!-- BOM自身的版本 -->
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
若有多个 BOM(如 Spring Boot + Spring Cloud),顺序决定版本优先级(后引入的 BOM 会覆盖先引入的同依赖版本)。
若需临时使用某个依赖的其他版本,可在<dependencies>中显式指定其版本,优先级高于 BOM:
解决依赖冲突
- 用
mvn dependency:tree命令分析依赖树,定位冲突依赖; - 用
exclusions排除不需要的传递依赖; - 用
dependencyManagement统一指定版本(优先级最高)。
最佳实践
- 核心依赖(业务代码)用
compile(默认); - 测试依赖用
test,避免打包到产物; - 容器提供的依赖(如 Servlet API)用
provided,避免冲突; - 数据库驱动等仅运行需要的依赖用
runtime; - 避免使用
system作用域(建议将本地 jar 安装到 Maven 仓库:mvn install:install-file); - 用
optional="true"标记非核心依赖,减少下游依赖冗余; - 统一版本:通过
dependencyManagement+ BOM 管理版本,避免硬编码。
常见问题
- Maven多模块构建时,需要把被依赖的模块先install到仓库吗?
在使用 Maven 进行多模块构建时,不需要手动将被依赖的模块先 install 到本地仓库。Maven 会自动处理模块之间的依赖关系。
当在父模块中运行 mvn install 或 mvn package 时,Maven 会按照模块的依赖顺序自动构建每个子模块。这意味着所有依赖的模块会在构建过程中被编译和打包,无需手动进行 install 操作。如果某个子模块依赖于其他子模块,确保它们在 pom.xml 中正确声明依赖关系即可,Maven 会处理好构建顺序。
[WARNING] The POM for org.example:xxx:jar:1.0-SNAPSHOT is missing, no dependency information available
-
Maven多模块,子模块单独install失败
1、需要把parent工程,也就是package是pom的那个工程先install一下;之后再install公共引入的模块,最后就可以单独编译子模块。
2、不用install,直接编译parent项目;这种方式只能在parent项目下进行,不能单独编译子模块。
Maven Wrapper
降级版本
mvn wrapper:wrapper -Dmaven=3.8.8
执行mvn相关命令时报错:
➜ mvn -v
Apache Maven 3.9.6 (bc0240f3c744dd6b6ec2920b3cd08dcc295161ae)
Maven home: D:\Develop\Java\apache-maven-3.9.6
Java version: 17.0.7, vendor: Oracle Corporation, runtime: D:\Develop\Java\JDK\oraclejdk17.0.7
Default locale: zh_CN, platform encoding: GBK
OS name: "windows 11", version: "10.0", arch: "amd64", family: "windows"
Idea里的Terminal和本机的终端的环境变量不同
例如在Idea的终端里切到项目根目录下执行mvn -v显示的jre用的是jdk11,而使用自带的终端切到项目根目录下执行mvn -v显示的jre用的是jdk17
Missing artifact jdk.tools:jdk.tools:jar:1.7
使用Maven管理项目时,遇到提示Missing artifact jdk.tools:jdk.tools:jar:1.7。但实际上Maven仓库里并没有这个依赖。
解决办法如下:修改项目的pom.xml,在依赖中增加如下的部分。
<dependency>
<groupId>jdk.tools</groupId>
<artifactId>jdk.tools</artifactId>
<version>1.7</version>
<scope>system</scope>
<systemPath>${JAVA_HOME}/lib/tools.jar</systemPath>
</dependency>
调试maven插件
有的时候Maven插件执行报错,希望能调试一下
Idea可以直接调试Maven插件的执行。以maven-compiler-plugin为例,首先需要将插件的坐标以依赖的形式引入:
<dependency>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
</dependency>
插件相关的类如下图所示,直接将断点打到CompilerMojo的execute方法里:

然后以Debug的方式执行插件,就可以看到打的断点已经生效了

问题解决方案
1.cannot download sources
使用Idea点开源码时

点击Download Sources后,弹出警告框

执行命令:mvn dependency:resolve -Dclassifier=sources
此命令会下载项目所有的依赖的源码
2.Idea中Maven插件无法下载
在
解决办法:将插件的坐标作为依赖放到项目依赖配置里,即<dependencies>里,然后刷新项目,重新加载maven依赖,这时就可以发现下载下来了,然后再改回来
3. 执行命令控制台乱码
Maven Runner添加VM Option:-Dfile.encoding=GBK,具体编码视操作系统编码而定

- Maven执行报错:No plugin found for prefix 'xxx'
[ERROR] No plugin found for prefix 'xxx' in the current project and in the plugin groups [org.apache.maven.plugins, org.codehaus.mojo] available from the repositories [local (/path/to/localRepository), nexus-aliyun (http://maven.aliyun.com/nexus/content/groups/public)] -> [Help 1] [ERROR]
"PKIX path building failed" and "unable to find valid certification path to requested target"
私服使用的https地址,安全证书过期或者没有,解决方案如下:
- 给使用的JDK安装可用的证书
- 使用maven命令时,添加以下参数,忽略安全检查
mvn -Dmaven.wagon.http.ssl.insecure=true -Dmaven.wagon.http.ssl.allowall=true
-Dmaven.wagon.http.ssl.ignore.validity.dates=true
- Dmaven.wagon.http.ssl.insecure=true - 允许放松ssl安全检查;
- Dmaven.wagon.http.ssl.allowall=true - 允许所有的X.509格式证书匹配,如果修改为false,则会执行和浏览器一致的检查;
- Dmaven.wagon.http.ssl.ignore.validity.dates=true - 忽略证书过期的问题
maven配置setting,使其忽略安全检查
<proxies>
<proxy>
<id>my-proxy</id>
<active>true</active>
<protocol>http</protocol>
<host>my-proxy-host</host>
<port>my-proxy-port</port>
<nonProxyHosts>localhost|127.0.0.1</nonProxyHosts>
<!-- 添加以下三个参数 -->
<sslHostConfig>
<!--指定是否信任所有证书-->
<all>true</all>
<!--指定使用的SSL协议版本-->
<sslProtocol>all</sslProtocol>
<!--指定是否启用SSL-->
<sslEnabled>true</sslEnabled>
<!--指定支持的SSL协议版本列表-->
<sslProtocols>TLSv1.2</sslProtocols>
<!--指定是否忽略证书验证-->
<ignoreCertificates>true</ignoreCertificates>
<!-- 指定是否信任自签名证书-->
<trustSelfSigned>true</trustSelfSigned>
<!-- 指定是否允许所有证书 -->
<allowAllCerts>true</allowAllCerts>
</sslHostConfig>
</proxy>
</proxies>

浙公网安备 33010602011771号