Maven使用总结

Maven仓库配置

参考博客:https://www.cnblogs.com/chanshuyi/p/quick-start-of-maven-pull.html

依赖管理

依赖声明

<dependency> 标签的核心是「坐标(groupId/artifactId/version)+ 作用域(scope)」,掌握以下关键点即可应对 99% 的场景:

  1. 必选属性:三个坐标唯一标识依赖,版本建议固定;
  2. 核心可选属性:scope控制依赖生效阶段,exclusions解决冲突,optional控制传递性;
  3. 特殊场景:classifier区分同版本变体,type="pom"引入 BOM;
  4. 避坑:少用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 版本(如jdk8jdk11);
  • 区分源码包(sources)、文档包(javadoc);
  • 区分操作系统包(如linux-x86_64windows-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),传递性受以下因素影响:

  1. scope:仅compile/runtime作用域的依赖会传递,test/provided/system不会;
  2. optionaloptional="true"的依赖不会传递;
  3. exclusions:显式排除的依赖不会传递;
  4. 版本冲突: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 中继承版本,实现版本统一管控。

核心特点:

  1. 版本统一:所有引入 BOM 的项目共用一套版本规则;
  2. 解耦版本与依赖:依赖的使用和版本管理分离;
  3. 解决冲突:优先使用 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 管理版本,避免硬编码。

常见问题

  1. 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

  1. 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方法里:

img

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

img

问题解决方案

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,具体编码视操作系统编码而定
在这里插入图片描述

  1. 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地址,安全证书过期或者没有,解决方案如下:

  1. 给使用的JDK安装可用的证书
  2. 使用maven命令时,添加以下参数,忽略安全检查
mvn -Dmaven.wagon.http.ssl.insecure=true -Dmaven.wagon.http.ssl.allowall=true 
	-Dmaven.wagon.http.ssl.ignore.validity.dates=true
  1. Dmaven.wagon.http.ssl.insecure=true - 允许放松ssl安全检查;
  2. Dmaven.wagon.http.ssl.allowall=true - 允许所有的X.509格式证书匹配,如果修改为false,则会执行和浏览器一致的检查;
  3. 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>
posted @ 2025-07-06 07:16  vonlinee  阅读(13)  评论(0)    收藏  举报