Maven

前言

  • Maven 是一个项目管理和整合工具。

  • Maven 为开发者提供了一套完整的构建生命周期框架。

  • 开发团队几乎不用花多少时间就能够自动完成工程的基础构建配置,因为 Maven 使用了一个标准的目录结构和一个默认的构建生命周期。

  • 在有多个开发团队环境的情况下,Maven 能够在很短的时间内使得每项工作都按照标准进行。

  • 因为大部分的工程配置操作都非常简单并且可复用,在创建报告、检查、构建和测试自动配置时,Maven 可以让开发者的工作变得更简单。

  • Maven 官网

  • Maven 教程

  • Maven 快速入门

  • Apache 软件基金会

  • Apache Maven 中央仓库

  • 阿里云 Maven 中央仓库

1、Maven

1.1 配置文件

  • POM(Project Object Model,项目对象模型)定义了项目的基本信息。

  • pom.xml 是 Maven 项目的核心文件,用于描述项目如何构建,声明项目依赖,等等。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

    <modelVersion>4.0.0</modelVersion> <!-- 指定了当前 POM 模型的版本,对于 Maven 2 和 Maven 3 来说,它只能是 4.0.0 -->
    <url>http://maven.apache.org</url>

    <groupId>com.qianchia</groupId> <!-- 定义了项目属于哪个组,这个组往往和项目所在的组织或公司存在关联,一般是使用组织或公司的域名 -->
    <artifactId>j2se</artifactId> <!-- 定义了当前项目在组中唯一的 ID,一般一个大项目组下面可能会包含多个子项目或子模块,而这个就是子项目或者子模块的名称 -->
    <version>1.0-SNAPSHOT</version> <!-- 指定这个项目当前的版本 -->
    <packaging>jar</packaging> <!-- 指定这个项目的打包方式 -->

    <name>j2se</name> <!-- 声明了一个对于用户更为友好的项目名称,方便后期的管理 -->

    <properties> <!-- 指定了 Maven 的一些重要属性 -->
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies> <!-- 指定这个项目的依赖包 -->
    <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>3.8.1</version>
    <scope>test</scope>
    </dependency>
    </dependencies>

    </project> <!-- project 是所有 pom.xml 的根元素,它还声明了一些 POM 相关的命名空间及 xsd 元素 -->

1.2 构建生命周期

  • Maven 构建生命周期就是 Maven 将一个整体任务划分为一个个的阶段,类似于流程图,按顺序依次执行。也可以指定该任务执行到中间的某个阶段结束。

  • Maven 的内部有三个构建生命周期,分别是 clean, default, site。其中 default 生命周期的核心阶段如下所示。

    1
    开始 --> validate --> compile --> test --> package --> verify --> install --> deploy --> 开始
  • 使用构建生命周期来完成构建工作。

    • 指定某个构建生命周期的阶段

      • 执行 mvn install 命令,将完成 validate, compile, test, package, verify, install 阶段,并将 package 生成的包发布到本地仓库中。
      • 其中某些带有连字符的阶段不能通过 shell 命令单独指定,例如:(pre-, post-, or process-*)。
    • 指定多个不同构建生命周期的阶段

      • 执行 mvn clean deploy 命令,首先完成的 clean lifecycle,将以前构建的文件清理。
      • 然后再执行 default lifecycle 的 validate, compile, test, package, verify, insstall, deploy 阶段,将 package 阶段创建的包发布到远程仓库中。

2、Maven 仓库

  • 所谓的仓库就是用于存放项目需要的 jar 包的。

  • Maven 采用一个仓库,多个项目的方式,让多个项目共享一个仓库里的相同 jar 包。

2.1 本地仓库

  • 默认仓库位置:打开文件 apache-maven\conf\settings.xml 可以看到仓库默认位置是 ${user.home}/.m2/repository

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
    <!-- localRepository
    | The path to the local repository maven will use to store artifacts.
    |
    | Default: ${user.home}/.m2/repository
    <localRepository>/path/to/local/repo</localRepository>
    -->
    </settings>
  • 修改仓库位置

    1
    2
    3
    4
    5
    <settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
    <localRepository>/Users/QianChia/.m2/maven/repository</localRepository>
    </settings>

2.2 远程仓库

  • 远程仓库

  • 默认会从 maven 官方提供的服务器(Apache Maven 中央仓库)下载 jar 包。

  • 而官方服务器在国外,网速很慢,而且容易卡断。

  • 为了便于快速下载相关 jar 包,可以使用国内阿里云的 maven 下载地址。

  • 修改 ${user.home}/.m2/settings.xml 文件,配置 远程仓库 地址。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    <?xml version="1.0" encoding="UTF-8"?>

    <settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">

    <!-- 设置 本地仓库 -->
    <localRepository>/Users/QianChia/.m2/maven/repository</localRepository>

    <servers>
    </servers>

    <!-- 配置 远程仓库 地址 -->
    <mirrors>
    <mirror>
    <id>aliyunmaven</id>
    <mirrorOf>*</mirrorOf>
    <name>阿里云公共仓库</name>
    <url>https://maven.aliyun.com/repository/public</url>
    </mirror>
    </mirrors>

    <profiles>
    </profiles>

    </settings>

3、Maven 项目

  • 在 Maven 项目中,项目骨架有这样的一个约定。
    • 有一个 pom.xml 用于维护当前项目都用了哪些 jar 包;
    • 项目主代码都位于 src/main/java 目录;
    • 项目测试代码都位于 src/test/java 目录。

3.1 创建项目

  • 在 Maven 中,我们可以通过 Archetype 生成项目骨架,实际上是在运行 maven-archetype-plugin 插件。

    1
    2
    # 创建 Maven 项目
    $ mvn archetype:generate
  • 执行这个命令后,后看到很多输出,有很多可用的 Archetype 供我们选择,每一个 Archetype 前面都会对应有一个编号,我们根据我们的需要,选择我们对应的骨架来创建项目就好了。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    Choose archetype:
    1: internal -> org.apache.maven.archetypes:maven-archetype-archetype (An archetype which contains a sample archetype.)
    2: internal -> org.apache.maven.archetypes:maven-archetype-j2ee-simple (An archetype which contains a simplifed sample J2EE application.)
    3: internal -> org.apache.maven.archetypes:maven-archetype-plugin (An archetype which contains a sample Maven plugin.)
    4: internal -> org.apache.maven.archetypes:maven-archetype-plugin-site (An archetype which contains a sample Maven plugin site.
    This archetype can be layered upon an existing Maven plugin project.)
    5: internal -> org.apache.maven.archetypes:maven-archetype-portlet (An archetype which contains a sample JSR-268 Portlet.)
    6: internal -> org.apache.maven.archetypes:maven-archetype-profiles ()
    7: internal -> org.apache.maven.archetypes:maven-archetype-quickstart (An archetype which contains a sample Maven project.)
    8: internal -> org.apache.maven.archetypes:maven-archetype-site (An archetype which contains a sample Maven site which demonstrates
    some of the supported document types like APT, XDoc, and FML and demonstrates how
    to i18n your site. This archetype can be layered upon an existing Maven project.)
    9: internal -> org.apache.maven.archetypes:maven-archetype-site-simple (An archetype which contains a sample Maven site.)
    10: internal -> org.apache.maven.archetypes:maven-archetype-webapp (An archetype which contains a sample Maven Webapp project.)
  • 然后再按照提示,输出新项目的 groupId、artifactId、version 和包名 package,一个 Maven 项目就创建成功了。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Define value for property 'groupId': com.qianchia          # 项目组名
    Define value for property 'artifactId': hello # 项目名称
    Define value for property 'version' 1.0-SNAPSHOT: : # 项目版本,默认是 1.0-SNAPSHOT,双冒号,使用默认值时,直接按回车即可
    Define value for property 'package' com.qianchia: : # 项目包名,默认与 groupId 相同,双冒号,使用默认值时,直接按回车即可
    Confirm properties configuration:
    groupId: com.qianchia
    artifactId: hello
    version: 1.0-SNAPSHOT
    package: com.qianchia
    Y: : # 确定填写的信息,双冒号,使用默认值时,直接按回车即可
  • 创建 Java 项目,运行成功会看到绿色的 BUILD SUCCESS。

    1
    2
    3
    4
    5
    6
    7
    8
    # 创建 Java 项目
    $ mvn archetype:generate -DgroupId=com.qianchia -DartifactId=j2se -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

    archetype:generate 表示创建个项目
    -DgroupId=com.qianchia 项目组名(包名)
    -DartifactId=j2se 项目名称
    -DarchetypeArtifactId=maven-archetype-quickstart 项目类型
    -DinteractiveMode=false 表示前面参数都给了,就不用一个一个地输入了
  • 创建 Web 项目,与 Maven 创建的 Java 项目结构类似,不过没有 java 目录,需要自己手动创建。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    # 创建 Web 项目
    $ mvn archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-webapp -DgroupId=com.qianchia -DartifactId=j2ee -DinteractiveMode=false

    archetype:generate 表示创建个项目
    -DarchetypeGroupId=org.apache.maven.archetypes
    -DarchetypeArtifactId=maven-archetype-webapp 项目类型
    -DgroupId=com.qianchia 项目组名(包名)
    -DartifactId=j2ee 项目名称
    -DinteractiveMode=false 表示前面参数都给了,就不用一个一个地输入了

3.2 项目文件

  • pom.xml 文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.qianchia</groupId>
    <artifactId>j2se</artifactId>
    <packaging>jar</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>j2se</name>

    <url>http://maven.apache.org</url>

    <dependencies>
    <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>3.8.1</version>
    <scope>test</scope>
    </dependency>
    </dependencies>
    </project>
  • 项目主代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    public class App {
    public String sayHello() {
    return "Hello World";
    }

    public static void main( String[] args ) {
    System.out.println(new App().sayHello());
    }
    }
  • 单元测试代码

    1
    2
    3
    4
    5
    6
    7
    8
    public class AppTest {
    @Test
    public void testSayHello() {
    App app = new App();
    String result = app.sayHello();
    assertEquals("Hello World", result);
    }
    }

3.3 添加 jar 包

  • 在 Java 中,我们进行单元测试时,基本上都是使用的 JUnit,要使用 JUnit 这个包,我们就需要引入这个依赖包,此时,我们就需要在 pom.xml 中添加以下依赖内容。

  • <dependency> 中的信息可以在 Apache Maven 中央仓库 中搜索的依赖包详细信息页面中获取,复制粘贴过来即可。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <dependencies>                                             <!-- 指定这个项目的依赖包,该元素下可以包含多个 dependency 元素以声明项目的依赖 -->

    <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13.2</version>
    <scope>test</scope> <!-- 表示依赖范围 -->
    </dependency>

    </dependencies>
  • 项目依赖的某一个 jar 包,有多个不同的版本,因而可能造成类包版本冲突

3.4 清理、编译

  • 在项目根目录下运行以下命令。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    # 进入到项目根目录
    $ cd j2se

    # 清理
    $ mvn clean

    # 编译
    $ mvn compile

    # 清理、编译
    $ mvn clean compile # 即 mvn clean & mvn compile
  • Maven 依次执行了 clean:clean、resources:resources 和 compiler:compile,都对应了 Maven 的生命周期及插件。

  • clean 告诉 Maven 清理项目输出目录 target。

    • 默认情况下,Maven 构建的所有输出都在 target 目录中;
    • clean 任务,删除 target 目录。
  • resources 告诉 Maven 链接资源文件。

    • resources 任务。
  • compile 告诉 Maven 编译项目主代码。

    • compile 任务,将项目主代码编译至 target/classes 目录。

3.5 测试

  • 测试用例编写完毕之后就可以调用 Maven 执行测试,运行以下命令。

    1
    2
    3
    4
    5
    # 测试
    $ mvn test

    # 清理、测试
    $ mvn clean test # 即 mvn clean & mvn test
  • Maven 依次执行了 clean:clean、resources:resources、compiler:compile、resources:testResources、compiler:testCompile 和 surefire:test。

3.6 打包

  • 打包就是将我们编写的应用打成 JAR 包或者 WAR 包

  • Maven 默认打包成 JAR 包。

  • 在 POM 文件中可以指定打包的类型。

    1
    2
    3
    4
    <packaging>jar</packaging>                                 <!-- 设置打包类型,打包成 jar 包,默认方式 -->


    <packaging>war</packaging> <!-- 设置打包类型,打包成 war 包 -->
  • 执行以下命令就可以完成打包。最后会看到一个绿色的 BUILD SUCCESS。

    1
    2
    3
    4
    5
    # 打包
    $ mvn package

    # 清理、打包
    $ mvn clean package # 即 mvn clean & mvn package
  • package 做了很多事情,编译,测试等操作,最后通过 jar:jar 任务负责打包,最后生成了一个 j2se-1.0-SNAPSHOT.jar 包,里面放了 App 这个类。

  • 这个最终生成的包会保存在 target 目录下,它是根据 artifact-version.jar 规则进行命名的。我们可以使用 finalName 属性来自定义该文件的名称。

  • 跳过单元测试

    • 方法一:mvn package -Dmaven.test.skip=true 不但跳过了单元测试的运行,同时也跳过了测试代码的编译。
    • 方法二:mvn package -DskipTests 跳过单元测试,但是会继续编译。
    • 如果没时间修改单元测试的 bug,或者单元测试编译错误,则使用第一种,不要使用第二种。
  • 设置 自定义包名

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    <project ...>

    <build>
    <plugins>
    <plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <executions>
    <execution>
    <goals>
    <goal>repackage</goal>
    </goals>
    </execution>
    </executions>

    <configuration>
    <finalName>helloWorld</finalName> <!-- 设置打包后的 包名称 -->
    </configuration>
    </plugin>
    </plugins>
    </build>
    </project>
  • 设置 打包成 war 包

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <packaging>war</packaging>                                 <!-- 设置打包类型,打包成 war 包 -->

    <build>
    <plugins>
    <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-war-plugin</artifactId> <!-- 添加 war 包打包插件 -->
    <configuration>
    <failOnMissingWebXml>false</failOnMissingWebXml>
    </configuration>
    </plugin>
    </plugins>
    </build>

3.7 安装

  • 如果别的项目要引用这个打包成的 JAR 包时,使用以下命令可以将项目输出的 JAR 包安装到了 Maven 本地仓库中。

  • 我们可以在本地的仓库文件夹中能看到这个项目的 pom 和 jar 包。

    1
    2
    3
    4
    5
    # 安装
    $ mvn install

    # 清理、安装
    $ mvn clean install # 即 mvn clean & mvn install
  • mvn clean install 和 mvn install 的区别

    • 根据 maven 在执行一个生命周期命令时,理论上讲,做 mvn install 得到的 jar 包应该是最新的,除非使用其他方式修改 jar 包的内容,但没有修改源代码。
    • 平时可以使用 mvn install,不使用 clean 会节省时间,但是最保险的方式还是 mvn clean install,这样可以生成最新的 jar 包或者其他包。
  • 使用场景

    • mvn clean package 依次执行了 clean、resources、compile、testResources、testCompile、test、package 等 7 个阶段。

    • package 命令完成了项目编译、单元测试、打包功能,但没有把打好的可执行 jar 包(war 包或其它形式的包)布署到本地 maven 仓库和远程 maven 私服仓库。

    • mvn clean install 依次执行了 clean、resources、compile、testResources、testCompile、test、package、install 等 8 个阶段。

    • install 命令完成了项目编译、单元测试、打包功能,同时把打好的可执行 jar 包(war 包或其它形式的包)布署到本地 maven 仓库,但没有布署到远程 maven 私服仓库。

    • mvn clean deploy 依次执行了 clean、resources、compile、testResources、testCompile、test、package、install、deploy 等 9 个阶段。

    • deploy 命令完成了项目编译、单元测试、打包功能,同时把打好的可执行 jar 包(war 包或其它形式的包)布署到本地 maven 仓库和远程 maven 私服仓库。

3.8 执行

  • 执行 Jar 包中的主类

    1
    2
    3
    4
    5
    # 执行 Jar 包中的主类 App
    $ java -cp target/j2se-1.0-SNAPSHOT.jar com.qianchia.App

    -cp 目录和 zip/jar 文件的类搜索路
    com.qianchia.App 主类路径
  • 由于带有 main 方法的类信息没有添加到 manifest 中,所以默认打包生成的 jar 是不能够直接运行的。

  • 使用 jd-gui 打开 jar 文件中的 META-INF/MANIFEST.MF 文件,将无法看到 Main-Class 一行。

  • 为了生成可执行 jar 文件,需要借助 Apache Maven Shade Plugin 来完成,我们需要在 pom.xml 文件中以下插件配置。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    <build>
    <plugins>
    <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin</artifactId>
    <version>3.2.4</version>
    <executions>
    <execution>
    <phase>package</phase>
    <goals>
    <goal>shade</goal>
    </goals>
    <configuration>
    <transformers>
    <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
    <mainClass>com.qianchia.App</mainClass> <!-- 主类路径 -->
    </transformer>
    </transformers>
    </configuration>
    </execution>
    </executions>
    </plugin>
    </plugins>
    </build>
  • 直接运行 Jar 包

    1
    2
    # 直接运行 Jar 包
    $ java -jar target/j2se-1.0-SNAPSHOT.jar
  • 后台运行 Jar 包

    1
    2
    # 后台运行 jar 包,输出日志到文件 nohup.out 中
    $ nohup java -jar target/j2se-1.0-SNAPSHOT.jar >nohup.out 2>&1 &

4、开发工具设置

4.1 IDEA 设置

  • 设置 Maven 和仓库路径

    • File -> Settings -> Build, Execute, Deployment -> Build Tools -> Maven。
    • 修改 Maven home directory: d:/software/apache-maven-3.5.0。
    • 修改 User settings file: d:\software\apache-maven-3.5.0\conf\settings.xml。
    • Local repository 会被自动识别为 d:\maven\repository。
  • 添加 jar 包

    • 修改 pom.xml 文件。
  • 创建 Java 项目

  • 创建 Web 项目

  • 创建过程缓慢

    • 有时候会碰到在 Idea 中创建 maven 项目很缓慢,多半是因为采用国外的仓库位置。
    • 所以第一个解决办法是设置 maven 使用阿里云下载路径。
    • 如果坚持使用国外的仓库位置,那么通过使用过程缓慢加快创建过程。
  • 父子项目

    • 通过 maven 可以创建父子-聚合项目。 所谓的父子项目,即有一个父项目,有多个子项目。
    • 这些子项目,在业务逻辑上,都归纳在这个父项目下,并且一般来说,都会有重复的 jar 包共享。
    • 所以常用的做法会把重复的 jar 包都放在父项目下进行依赖,那么子项目就无需再去依赖这些重复的 jar 包了。
    • 所谓的子项目,其实是 maven module。

4.2 Eclipse 设置

  • 设置 Maven 路径

    • 菜单 -> Window -> Preferences -> Maven -> Installations。
    • 指定 d:\software\apache-maven-3.5.0。
    • 把原来的那个低版本 maven 删除掉,如果有的话。
  • 设置仓库路径

    • 菜单 -> Window -> Preferences -> Maven -> User Settings。
    • Global Settings 和 User Settings 都使用:d:\software\apache-maven-3.5.0\conf\settings.xml。
    • 点击一下 Reindex,确保 local Repository 为:d:/maven/repository。
  • 添加 jar 包

    • 编辑 pom.xml 文件。
  • 重建本地仓库

    • 倘若在给 maven 项目添加 jar 中无法搜索到 jar 包,那么可以按照如下行为操作一遍。
    • 菜单 -> Window -> Show View-> Other -> Maven -> Maven Repositories -> Local Repository -> Rebuild Index。
  • 创建 Java 项目

  • 创建 Web 项目

  • 创建 SSM 项目

  • 导入 SSM 项目

  • 父子项目

5、依赖冲突

  • 依赖冲突是指项目依赖的某一个 jar 包,有多个不同的版本,因而造成类包版本冲突。

  • 依赖冲突经常是类包之间的间接依赖引起的。每个显式声明的类包都会依赖于一些其它的隐式类包,这些隐式的类包会被 maven 间接引入进来,从而造成类包冲突。

  • 如何解决依赖冲突,首先查看产生依赖冲突的 jar 包,其次找出我们不想要的依赖类 jar,手工将其排除在外就可以了。

5.1 查看依赖冲突

5.1.1 Maven 命令

  • Maven 命令查看依赖冲突

    1
    2
    # 检查版本冲突
    $ mvn -Dverbose dependency:tree
  • 当敲入上述命令时,控制台会出现如下内容。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    [INFO] org.example:hello:jar:1.0-SNAPSHOT
    [INFO] +- org.springframework:spring-context:jar:5.2.7.RELEASE:compile
    [INFO] | +- (org.springframework:spring-aop:jar:5.2.7.RELEASE:compile - omitted for conflict with 5.2.0.RELEASE)
    [INFO] | +- org.springframework:spring-beans:jar:5.2.7.RELEASE:compile
    [INFO] | | \- (org.springframework:spring-core:jar:5.2.7.RELEASE:compile - omitted for duplicate) # 包含 spring-core 5.2.7
    [INFO] | +- org.springframework:spring-core:jar:5.2.7.RELEASE:compile
    [INFO] | | \- org.springframework:spring-jcl:jar:5.2.7.RELEASE:compile
    [INFO] | \- org.springframework:spring-expression:jar:5.2.7.RELEASE:compile
    [INFO] | \- (org.springframework:spring-core:jar:5.2.7.RELEASE:compile - omitted for duplicate) # 包含 spring-core 5.2.7
    [INFO] \- org.springframework:spring-aop:jar:5.2.0.RELEASE:compile
    [INFO] +- (org.springframework:spring-beans:jar:5.2.0.RELEASE:compile - omitted for conflict with 5.2.7.RELEASE)
    [INFO] \- (org.springframework:spring-core:jar:5.2.0.RELEASE:compile - omitted for conflict with 5.2.7.RELEASE) # 包含 spring-core 5.2.0
  • 其中 omitted for duplicate 表示有 jar 包被重复依赖。

  • 最后写着 omitted for conflict with xxx 的,说明和别的 jar 包版本冲突了,而该行的 jar 包不会被引入。

  • 比如上面有一行最后写着 omitted for conflict with 5.2.7.RELEASE,表示 spring-core 5.2.0 版本不会被项目引用,而 spring-core 5.2.7 版本会被项目引用。

5.1.2 IDEA 插件

  • 在 IDEA 中可以安装 Maven Helper 插件来检查依赖冲突。

  • 插件安装成功后,点开 pom.xml 文件,在底部会发现多了一个 Dependency Analyzer 视图。

    • Conflicts(查看冲突)
    • All Dependencies as List(列表形式查看所有依赖)
    • All Dependencies as Tree(树形式查看所有依赖)

5.2 解决冲突

  • 第一声明者优先原则

    • 谁先定义的就用谁的传递依赖,即在 pom.xml 文件自上而下,先声明的 jar 坐标,就先引用该 jar 的传递依赖。
  • 路径近者优先原则

    • 直接依赖级别高于传递依赖。
    • 因此可以在最先的 pom.xml 添加产生冲突的 jar 包中的传递依赖。
  • 排除依赖

    • 如果是 IDEA,可以使用 Maven Helper 插件进行排除。点开 pom.xml,切换到 Dependency Analyzer 视图,选择 All Dependencies as Tree,点击要排除的 jar,右键会出现 Execlude 选项。

    • 它产生的效果和如下配置是一样。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      <dependencies>
      <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.2.7.RELEASE</version>

      <exclusions> <!-- 排除 不想引用的 传递依赖 -->
      <exclusion>
      <artifactId>spring-core</artifactId> <!-- 排除 spring-context 中的传递依赖 spring-core -->
      <groupId>org.springframework</groupId>
      </exclusion>
      </exclusions>
      </dependency>

      <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aop</artifactId>
      <version>5.2.0.RELEASE</version>
      </dependency>
      </dependencies>
  • 版本锁定

    • 使用 dependencyManagement 进行版本锁定,dependencyManagement 可以统一管理项目的版本号,确保应用的各个项目的依赖和版本一致。

    • dependencyManagement 只是声明依赖,并不自动实现引入,因此子项目需要显示的声明需要用的依赖。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      <dependencyManagement>                                     <!-- 声明 依赖版本 -->
      <dependencies>
      <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>5.2.0.RELEASE</version> <!-- 指定引入是 spring core 5.2.0 的包 -->
      </dependency>
      </dependencies>
      </dependencyManagement>

      <dependencies>
      <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.2.7.RELEASE</version>
      </dependency>

      <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aop</artifactId>
      <version>5.2.0.RELEASE</version>
      </dependency>
      </dependencies>
文章目录
  1. 1. 前言
  2. 2. 1、Maven
    1. 2.1. 1.1 配置文件
    2. 2.2. 1.2 构建生命周期
  3. 3. 2、Maven 仓库
    1. 3.1. 2.1 本地仓库
    2. 3.2. 2.2 远程仓库
  4. 4. 3、Maven 项目
    1. 4.1. 3.1 创建项目
    2. 4.2. 3.2 项目文件
    3. 4.3. 3.3 添加 jar 包
    4. 4.4. 3.4 清理、编译
    5. 4.5. 3.5 测试
    6. 4.6. 3.6 打包
    7. 4.7. 3.7 安装
    8. 4.8. 3.8 执行
  5. 5. 4、开发工具设置
    1. 5.1. 4.1 IDEA 设置
    2. 5.2. 4.2 Eclipse 设置
  6. 6. 5、依赖冲突
    1. 6.1. 5.1 查看依赖冲突
      1. 6.1.1. 5.1.1 Maven 命令
      2. 6.1.2. 5.1.2 IDEA 插件
    2. 6.2. 5.2 解决冲突
隐藏目录