Maven 指导手册

1,147 阅读20分钟

本文主要内容来源于官网。

使用jdk1.8、maven3.8.4版本。

简介

maven是一个自动化构建工具,用来做项目构建和管理,应用于java平台。

早期的项目很多Ant项目,而JAR包的管理都是通过CVS管理,项目维护起来很麻烦。

The result is a tool that can now be used for building and managing any Java-based project. We hope that we have created something that will make the day-to-day work of Java developers easier and generally help with the comprehension of any Java-based project.

maven的目标就是使开发者在短时间内了解开发中的状态。关注:

  • 简化构建过程,maven可以在一定程度上让开发者不必了解更多细节。
  • 提供统一的构建系统,maven通过POM(project object model )项目对象模型)和一组插件完成项目构建,其中POM就是maven pom.xml,是xml格式的描述项目信息、开发者信息、依赖关系等一系列信息的文件,作为开发者如果熟悉了一个maven项目,那么就会了解所有的maven项目的构建。制定标准,在很大程度上节约了浏览项目的时间。
  • 提供有优质的项目信息,maven中的POM提供这些项目信息一个很重要的信息就是依赖信息,还可以提供测试报告。
  • 为开发实践提供指导,如项目结构、项目发布流程、单元测试规范等。

我们现在应用maven主要在于依赖管理、持续集成包括编译、构建、发布等。

下载

maven下载地址:maven.apache.org/download.cg…

maven-downlowad.PNG

配置安装

预设环境

maven 3.3及以上版本需要jdk1.7及以上版本。

$ echo $JAVA_HOME
C:\Program Files\Java\jdk1.8.0_251

安装及配置

  1. 配置maven安装目录,变量MAVEN_HOME,如D:\develop\maven\apache-maven-3.8.4
  2. 配置maven bin目录,可以全局使用mvn命令,在Path变量下增加%MAVEN_HOME%\bin

检查

# 查看版本
$ mvn -v 
Apache Maven 3.8.4 (9b656c72d54e5bacbed989b64718c159fe39b537)
Maven home: D:\develop\maven\apache-maven-3.8.4
Java version: 1.8.0_251, vendor: Oracle Corporation, runtime: C:\Program Files\Java\jdk1.8.0_251\jre
Default locale: zh_CN, platform encoding: GBK
OS name: "windows 10", version: "10.0", arch: "amd64", family: "windows"

原型

原型为maven提供了一套项目模板及工具。在eclipse、idea或者命令行创建maven项目时都会用到原型。

原型的设计思想是为maven提供统一的项目结构,加快开发速度。

使用原型需要调用构建目标mvn archetype:generate

组成

maven的原型在jar包中的,包含了原型信息和 Velocity模板。

列表

maven提供了一系列原型。

项目标识描述
maven-archetype-archetypeAn archetype to generate a sample archetype.
maven-archetype-j2ee-simpleAn archetype to generate a simplifed sample J2EE application.
maven-archetype-pluginAn archetype to generate a sample Maven plugin.
maven-archetype-plugin-siteAn archetype to generate a sample Maven plugin site.
maven-archetype-portletAn archetype to generate a sample JSR-268 Portlet.
maven-archetype-quickstart生成简单的maven项目。
maven-archetype-simpleAn archetype to generate a simple Maven project.
maven-archetype-siteAn archetype to generate a sample Maven site which demonstrates some of the supported document types like APT, Markdown, XDoc, and FML and demonstrates how to i18n your site.
maven-archetype-site-simpleAn archetype to generate a sample Maven site.
maven-archetype-site-skinAn archetype to generate a sample Maven Site Skin.
maven-archetype-webappAn archetype to generate a sample Maven Webapp project.

创建一个项目

先创建一个项目,方便后续的操作。

新建项目

使用maven的原型插件maven-archetype-plugin创建新项目,关于原型在后面章节介绍。

其中:-DgroupId-DartifactId-DarchetypeArtifactId-DarchetypeVersion分别指定了组织、项目标识、原型、版本,使用-DinteractiveMode关闭互动模式,命令执行后不需要手动设置。

  • -D 参数设置系统属性,maven使用java的参数设置,向jvm加入参数。
$ mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=my-app -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.4 -DinteractiveMode=false

[INFO] Scanning for projects...
......
......
......
[INFO] Using following parameters for creating project from Archetype: maven-archetype-quickstart:1.4
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: groupId, Value: com.mycompany.app
[INFO] Parameter: artifactId, Value: my-app
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] Parameter: package, Value: com.mycompany.app
[INFO] Parameter: packageInPathFormat, Value: com/mycompany/app
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] Parameter: package, Value: com.mycompany.app
[INFO] Parameter: groupId, Value: com.mycompany.app
[INFO] Parameter: artifactId, Value: my-app
[INFO] Project created from Archetype in dir: D:\workspace\tmp\my-app
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  3.415 s
[INFO] Finished at: 2022-03-12T17:55:41+08:00
[INFO] ------------------------------------------------------------------------

新生成项目目录结构,在window下使用tree命令查看:

D:.
│  pom.xml
│
└─src
    ├─main
    │  └─java
    │      └─com
    │          └─mycompany
    │              └─app
    │                      App.java
    │
    └─test
        └─java
            └─com
                └─mycompany
                    └─app
                            AppTest.java

目录说明

maven的一个特性为开发实践提供指定,其中包括项目结构。通用的项目结构,可以让开发人员快速熟悉项目

src/main/java 应用源文件
src/main/resources 应用资源文件
src/main/filters 资源过滤文件
src/main/webapp web应用源文件
src/test/java 测试源文件
src/test/resources 测试资源文件
src/test/filters 测试资源过滤文件
src/it 集成测试文件
src/assembly 打包描述
src/site 站点
LICENSE.txt 项目许可证
NOTICE.txt 提示和依赖说明
README.txt 项目间接、安装等信息

POM

POM(Project Object Model) 项目对象模型,将maven项目信息存储在xml文件pom.xml中。

项目中信息包括开发人员、缺陷跟踪、组织、许可证、项目URL、依赖关系等。

目前pom的版本是4.0.0

最小pom

pom.xml 文件必须的节点:

  • project 根节点

  • modelVersion 版本,固定4.0.0

  • groupId 组织,一般根据域名取

  • artifactId 项目

  • version 版本

例:

<project>
  <modelVersion>4.0.0</modelVersion>
    
  <groupId>com.mycompany.app</groupId>
  <artifactId>my-app</artifactId>
  <version>1</version>
</project>

groupIdartifactIdversion定义了应用包在仓库中的位置,实例中组件包的名称为com.mycompany.app:my-app:1

Super POM

maven默认pom.xml,正常情况下项目的所有pom都继承自Super POM。

查看Super POM 的方法是:

  1. 创建一个最小pom.xml
  2. 在最小pom.xml目录执行命令mvn help:effective-pom

例:

$ mvn help:effective-pom
[INFO] Scanning for projects...
......
......
......
[INFO]
[INFO] ----------------------< com.mycompany.app:my-app >----------------------
[INFO] Building my-app 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-help-plugin:3.2.0:effective-pom (default-cli) @ my-app ---
[INFO]
Effective POMs, after inheritance, interpolation, and profiles are applied:

<?xml version="1.0" encoding="GBK"?>
<!-- ====================================================================== -->
<!--                                                                        -->
<!-- Generated by Maven Help Plugin on 2022-03-12T18:01:04+08:00            -->
<!-- See: http://maven.apache.org/plugins/maven-help-plugin/                -->
<!--                                                                        -->
<!-- ====================================================================== -->
<!-- ====================================================================== -->
<!--                                                                        -->
<!-- Effective POM for project 'com.mycompany.app:my-app:jar:1.0-SNAPSHOT'  -->
<!--                                                                        -->
<!-- ====================================================================== -->
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.mycompany.app</groupId>
  <artifactId>my-app</artifactId>
  <version>1.0-SNAPSHOT</version>
  <name>my-app</name>
  <url>http://www.example.com</url>
  <properties>
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
  <repositories>
    <repository>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
      <id>central</id>
      <name>Central Repository</name>
      <url>https://repo.maven.apache.org/maven2</url>
    </repository>
  </repositories>
  <pluginRepositories>
    <pluginRepository>
      <releases>
        <updatePolicy>never</updatePolicy>
      </releases>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
      <id>central</id>
      <name>Central Repository</name>
      <url>https://repo.maven.apache.org/maven2</url>
    </pluginRepository>
  </pluginRepositories>
  <build>
    <sourceDirectory>D:\workspace\tmp\my-app\src\main\java</sourceDirectory>
    <scriptSourceDirectory>D:\workspace\tmp\my-app\src\main\scripts</scriptSourceDirectory>
    <testSourceDirectory>D:\workspace\tmp\my-app\src\test\java</testSourceDirectory>
    <outputDirectory>D:\workspace\tmp\my-app\target\classes</outputDirectory>
    <testOutputDirectory>D:\workspace\tmp\my-app\target\test-classes</testOutputDirectory>
    <resources>
      <resource>
        <directory>D:\workspace\tmp\my-app\src\main\resources</directory>
      </resource>
    </resources>
    <testResources>
      <testResource>
        <directory>D:\workspace\tmp\my-app\src\test\resources</directory>
      </testResource>
    </testResources>
    <directory>D:\workspace\tmp\my-app\target</directory>
    <finalName>my-app-1.0-SNAPSHOT</finalName>
    <pluginManagement>
      <plugins>
        <plugin>
          <artifactId>maven-antrun-plugin</artifactId>
          <version>1.3</version>
        </plugin>
        <plugin>
          <artifactId>maven-assembly-plugin</artifactId>
          <version>2.2-beta-5</version>
        </plugin>
        <plugin>
          <artifactId>maven-dependency-plugin</artifactId>
          <version>2.8</version>
        </plugin>
        <plugin>
          <artifactId>maven-release-plugin</artifactId>
          <version>2.5.3</version>
        </plugin>
        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.1.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.8.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>2.22.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-jar-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-install-plugin</artifactId>
          <version>2.5.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>2.8.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-site-plugin</artifactId>
          <version>3.7.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-project-info-reports-plugin</artifactId>
          <version>3.0.0</version>
        </plugin>
      </plugins>
    </pluginManagement>
    <plugins>
      <plugin>
        <artifactId>maven-clean-plugin</artifactId>
        <version>3.1.0</version>
        <executions>
          <execution>
            <id>default-clean</id>
            <phase>clean</phase>
            <goals>
              <goal>clean</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <artifactId>maven-resources-plugin</artifactId>
        <version>3.0.2</version>
        <executions>
          <execution>
            <id>default-testResources</id>
            <phase>process-test-resources</phase>
            <goals>
              <goal>testResources</goal>
            </goals>
          </execution>
          <execution>
            <id>default-resources</id>
            <phase>process-resources</phase>
            <goals>
              <goal>resources</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <artifactId>maven-jar-plugin</artifactId>
        <version>3.0.2</version>
        <executions>
          <execution>
            <id>default-jar</id>
            <phase>package</phase>
            <goals>
              <goal>jar</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.8.0</version>
        <executions>
          <execution>
            <id>default-compile</id>
            <phase>compile</phase>
            <goals>
              <goal>compile</goal>
            </goals>
          </execution>
          <execution>
            <id>default-testCompile</id>
            <phase>test-compile</phase>
            <goals>
              <goal>testCompile</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>2.22.1</version>
        <executions>
          <execution>
            <id>default-test</id>
            <phase>test</phase>
            <goals>
              <goal>test</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <artifactId>maven-install-plugin</artifactId>
        <version>2.5.2</version>
        <executions>
          <execution>
            <id>default-install</id>
            <phase>install</phase>
            <goals>
              <goal>install</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <artifactId>maven-deploy-plugin</artifactId>
        <version>2.8.2</version>
        <executions>
          <execution>
            <id>default-deploy</id>
            <phase>deploy</phase>
            <goals>
              <goal>deploy</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <artifactId>maven-site-plugin</artifactId>
        <version>3.7.1</version>
        <executions>
          <execution>
            <id>default-site</id>
            <phase>site</phase>
            <goals>
              <goal>site</goal>
            </goals>
            <configuration>
              <outputDirectory>D:\workspace\tmp\my-app\target\site</outputDirectory>
              <reportPlugins>
                <reportPlugin>
                  <groupId>org.apache.maven.plugins</groupId>
                  <artifactId>maven-project-info-reports-plugin</artifactId>
                </reportPlugin>
              </reportPlugins>
            </configuration>
          </execution>
          <execution>
            <id>default-deploy</id>
            <phase>site-deploy</phase>
            <goals>
              <goal>deploy</goal>
            </goals>
            <configuration>
              <outputDirectory>D:\workspace\tmp\my-app\target\site</outputDirectory>
              <reportPlugins>
                <reportPlugin>
                  <groupId>org.apache.maven.plugins</groupId>
                  <artifactId>maven-project-info-reports-plugin</artifactId>
                </reportPlugin>
              </reportPlugins>
            </configuration>
          </execution>
        </executions>
        <configuration>
          <outputDirectory>D:\workspace\tmp\my-app\target\site</outputDirectory>
          <reportPlugins>
            <reportPlugin>
              <groupId>org.apache.maven.plugins</groupId>
              <artifactId>maven-project-info-reports-plugin</artifactId>
            </reportPlugin>
          </reportPlugins>
        </configuration>
      </plugin>
    </plugins>
  </build>
  <reporting>
    <outputDirectory>D:\workspace\tmp\my-app\target\site</outputDirectory>
  </reporting>
</project>


[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  6.163 s
[INFO] Finished at: 2022-03-12T18:01:04+08:00
[INFO] ------------------------------------------------------------------------

主要标签说明

基本标签

groupId

组织名

artifactId

项目标识

version

版本

packaging

支持pom, jar, maven-plugin, ejb, war, ear, rar ,默认值为 jar,不同类型定义了不同的构建目标。

POM 关系

pom中项目间的关系包含三种依赖、继承、聚合。

依赖关系

一个项目依赖于另一个项目构建及运行。

dependencies

一系列的依赖

 <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <type>jar</type>
      <scope>test</scope>
      <optional>true</optional>
    </dependency>
    ...
  </dependencies>
depnedency
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <type>jar</type>
    <scope>test</scope>
    <optional>true</optional>
    <exclusions>
        <exclusion>
          <groupId>*</groupId>
          <artifactId>*</artifactId>
        </exclusion>
    </exclusions>
</dependency>

groupIdartifactIdversion前面已经提到,定义了应用包在仓库中的位置。

type

默认为jar,一般是依赖文件的扩展名

classifier

分类,用于groupIdartifactIdversion相同,内容不同的情况。打包后标识位于GAV之后,也就是version之后,例如,用maven-install-plugin插件将包安装到本地仓库。下面实例是将jar包安装到本地,指定-Dclassifier=1.8,其中

$ mvn install:install-file -Dclassifier=1.8 -DskipTests=true -Dfile=D:/develop/maven/repository/commons-io/commons-io/2.11.0/commons-io-2.11.0.jar -DgroupId=commons-io -DartifactId=commons-io -Dversion=2.11.0 -Dpackaging=jar
[INFO] Scanning for projects...
[INFO]
[INFO] ----------------------< com.mycompany.app:my-app >----------------------
[INFO] Building my-app 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-install-plugin:2.5.2:install-file (default-cli) @ my-app ---
[INFO] Installing D:\develop\maven\repository\commons-io\commons-io\2.11.0\commons-io-2.11.0.jar to D:\develop\maven\repository\commons-io\commons-io\2.11.0\commons-io-2.11.0-1.8.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  0.709 s
[INFO] Finished at: 2022-03-12T18:03:42+08:00
[INFO] ------------------------------------------------------------------------
scope

作用域,指定了编译、运行、测试期间的classpath,也限制了依赖的传递性,包括:

  • compile 默认的作用域范围,未指定时使用这个值。在**所有classpath(编译、运行、测试)**下都是有效的,依赖关系会传递到依赖项目。

  • provided 与compile类似,此作用域表示期望依赖由JDK或者容器提供。只在编译和测试阶段的classpath中,不可传递依赖。例如,servlet-api由容器提供。

  • runtime 此作用域表示在编译期不需要此依赖,在运行时需要依赖项。在运行和测试阶段的classpath中,不在编译阶段的classpath中。例如,jdbc驱动。

  • test 此作用域表示应用正常使用不需要的依赖项,只在测试和执行阶段的classpath中,不可传递依赖。例如,junit单元测试包。

  • system 此作用域与provided类似,只在编译和测试阶段的classpath中,但必须显式的指定依赖包,不由maven查找。

systemPath

作用域指定为system时使用此标签。路径必须是绝对路径。官方建议使用变量,例如,${java.home}/lib

<dependency>
    <groupId>com.mycompany</groupId>
    <artifactId>my-core</artifactId>
    <scope>system</scope>
    <version>1.0.1</version>
    <systemPath>${java.home}\lib\my-core.jar</systemPath>
</dependency>
optional

一个项目本身是依赖项,将自身依赖标识为可选。如果项目A依赖于项目B来在编译一部分代码,但在运行期不需要这部分代码,那么B项目可能不需要被引入。

  • => 表示必须依赖

  • -->表示可选依赖

    项目X依赖于A,项目A依赖于B,构建A时,关系为A=>B,构建X时,关系为X=>A-->B,正常情况下X中将不包含B依赖包,如果需要B依赖,则需要加optional移除或改成false,也可以在X中单独引入B依赖。

version

定义了依赖项的版本需求。软需求(Soft requirements )可以被依赖树中其他地方具有相同的groupIdartifactId的不同版本替代。硬需求(Hard requirements)要求特定的一个或多个版本。例如:

  • 1.0 软需求版本,如果在依赖树中更早的没有其他版本出现,则使用1.0版本
  • [1.0] 硬需求版本,只能使用1.0版本
  • (,1.0] 硬需求版本,只能使用<=1.0版本
  • [1.2,1.3] 硬需求版本,只能使用介于1.2和1.3的版本
  • [1.0,2.0) 硬需求版本,只能使用1.0<=version<2.0
  • [1.5,) 硬需求版本,只能使用>=1.5
  • (,1.0],[1.2,) 硬需求版本,只能使用version<1.0 或者 version>=1.2,多个版本需求用逗号隔开
  • (,1.1),(1.1,) 硬需求版本,任何非1.1版本

maven会选择所有满足硬需求的依赖的最高版本,如果没有依赖满足所有硬需求,构建失败。

当找不到任何版本信息时,在idea中maven会提示错误,如:

<!-- 大额存单facade包 -->
<dependency>
    <groupId>com.csii.pcbs</groupId>
    <artifactId>de-facade</artifactId>
    <version>[1.3,1.4]</version>
</dependency>

提示:

No versions avaliable for com.csii.pcbs:de-facade:jar:[1.3,1.4] within spercified range

版本顺序:

何为高版本,何为低版本?

对于纯数字的,1.0、1.2、1.3等很明显,但是对于其他的不一定很好判定。

官网给出了很多案例,此处不详细描述。参考:maven.apache.org/pom.html

可以使用maven提供的工具检查版本顺序:

# 本地使用的maven 3.8.4
$ java -jar ${MAVEN_HOME}/lib/maven-artifact-3.8.4.jar 1.2 3 1-a 3-a 2-c 1.5
Display parameters as parsed by Maven (in canonical form and as a list of tokens) and comparison result:
1. 1.2 -> 1.2; tokens: [1, 2]
   1.2 < 3
2. 3 -> 3; tokens: [3]
   3 > 1-a
3. 1-a -> 1-a; tokens: [1, [a]]
   1-a < 3-a
4. 3-a -> 3-a; tokens: [3, [a]]
   3-a > 2-c
5. 2-c -> 2-c; tokens: [2, [c]]
   2-c > 1.5
6. 1.5 -> 1.5; tokens: [1, 5]

关于正式版本和快照版本,参考版本及快照

exclusions

排除依赖项,不使用依赖的依赖项即排除指定的传递依赖。如果需要排除多个,则增加多个exclusion

exclusion

此标签可以有效的排除一些传递依赖,每个标签下包含groupIdartifactId

排除依赖的原因在于:

  • 原有的传递依赖项指定的scope作用域不正确,需要排除,引入新的依赖项
  • 原有的传递依赖项和项目中其他的依赖项存在冲突,冲突会导致项目找不到对应的类或者使用错误的依赖版本,需要排除,显式的引入依赖项。

下面实例:排除org.apache.maven:maven-embedder:2.0包下的org.apache.maven:maven-core依赖

<dependency>  
    <groupId>org.apache.maven</groupId>  
    <artifactId>maven-embedder</artifactId>   
    <version>2.0</version>   
    <exclusions>     
        <exclusion>       
            <groupId>org.apache.maven</groupId>       
            <artifactId>maven-core</artifactId>     
        </exclusion>   
    </exclusions>
</dependency>

optional的差异:

optional是排除自身,optional修饰的依赖,可能被引入,也可能不被引入;exlcusions/exlcusion排除传递依赖,排除的是下一级的依赖。

  1. optional示例

pcbs平台测试包com.csii.pcbs:pcbs-aplt-test依赖于org.springframework:spring-test

<project xmlns="http://maven.apache.org/POM/4.0.0">	
    <modelVersion>4.0.0</modelVersion>	
    <groupId>com.csii.pcbs</groupId>	
    <artifactId>pcbs-aplt-test</artifactId>		
    <dependencies>		
        <dependency>			
            <groupId>org.springframework</groupId>			
            <artifactId>spring-test</artifactId>			
            <optional>true</optional>		
        </dependency>	
    </dependencies>
</project>
flowchart TD
pcbs-aplt-test(pcbs-aplt-test) -.可选依赖.-> spring-test(spring-test)
  1. exlcusions/exlcusion示例

pcbs平台测试包com.csii.pcbs:dp-is-oltp依赖于com.csii.pcbs:pcbs-oltp-dependenciescom.csii.pcbs:pcbs-oltp-dependencies依赖于com.alibaba:dubbostax:stax-api

<project xmlns="http://maven.apache.org/POM/4.0.0">

	<modelVersion>4.0.0</modelVersion>

	<groupId>com.csii.pcbs</groupId>
	<artifactId>dp-is-oltp</artifactId>

	<dependencies>
		<dependency>
			<groupId>com.csii.pcbs</groupId>
			<artifactId>pcbs-oltp-dependencies</artifactId>
			<version>3.0.6</version>
			<type>pom</type>
			<exclusions>
				<exclusion>
					<groupId>com.alibaba</groupId>
					<artifactId>dubbo</artifactId>
				</exclusion>
				<exclusion>
					<groupId>stax</groupId>
					<artifactId>stax-api</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
	</dependencies>
</project>
flowchart TD
dp-is-oltp(dp-is-oltp) --> pcbs-oltp-dependencies(pcbs-oltp-dependencies)
pcbs-oltp-dependencies(pcbs-oltp-dependencies) --> com.alibaba(com.alibaba)
pcbs-oltp-dependencies(pcbs-oltp-dependencies) --> stax-api(stax-api)
dp-is-oltp(dp-is-oltp) -.传递依赖.-> com.alibaba(com.alibaba)
dp-is-oltp(dp-is-oltp) -.传递依赖.-> stax-api(stax-api)

继承关系

作为父项目,packaging要求必须为pom类型。关于Super POM 参考[Super POM](# Super POM)

简单使用

在父项目中定义:

<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>org.codehaus.mojo</groupId>
  <artifactId>my-parent</artifactId>
  <version>2.0</version>
  <packaging>pom</packaging>
</project>

在子项目中引用:

<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">  <modelVersion>4.0.0</modelVersion>  <parent>    <groupId>org.codehaus.mojo</groupId>    <artifactId>my-parent</artifactId>    <version>2.0</version>    <!-- relativePath 非必须,优先查找此位置,之后才会查找本地仓库、远程仓库-->    <relativePath>../my-parent</relativePath>  </parent>  <artifactId>my-project</artifactId></project>
子项目继承元素

子项目从父项目继承包括:

  • groupId
  • version
  • description
  • url
  • inceptionYear
  • organization
  • licenses
  • developers
  • contributors
  • mailingLists
  • scm
  • issueManagement
  • ciManagement
  • properties
  • dependencyManagement
  • dependencies
  • repositories
  • pluginRepositories
  • build
    • plugin executions with matching ids
    • plugin configuration
    • etc.
  • reporting
  • profiles

不继承元素:

  • artifactId
  • name
  • prerequisites
dependencyManagement

用于管理依赖项。

在下面的示例中,父项目定义了dependencyManagement ,指定了org.codehaus.mojo:my-core这样一个依赖项,版本号1.0.0,子项目依赖了org.codehaus.mojo:my-core,但是未指定版本号,这时候maven可以自行填充版本号为1.0.0,不需要显式的指定依赖版本。但是,如果在子项目依赖中指定其他版本号,如2.0.0,那么子项目依赖的就是2.0.0。

在父项目中定义:

<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>org.codehaus.mojo</groupId>
  <artifactId>my-parent</artifactId>
  <version>2.0</version>
  <packaging>pom</packaging>
  
  <dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>my-core</artifactId>
            <version>1.0.0</version>
        </dependency>
    </dependencies>
  </dependencyManagement>
</project>

在子项目中引用:

<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <parent>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>my-parent</artifactId>
    <version>2.0</version>
    <!-- relativePath 非必须,优先查找此位置,之后才会查找本地仓库、远程仓库-->
    <relativePath>../my-parent</relativePath>
  </parent>

  <artifactId>my-project</artifactId>
    
  <dependencies>
    <dependency>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>my-core</artifactId>
    </dependency>
  </dependencies>
</project>

dependencyManagement最大的意义在于能有有效的统一管理依赖项的版本。

需要注意:

  • 传递依赖中的versionscope也会被dependencyManagement管理,可能会导致一些问题,两个模块依赖了同一个依赖项但是版本不同,可能会出现版本冲突。

    这就需要用到之前提到的exclusions/exclusion标签,进行排包操作。可以考虑使用maven-dependency-plugin插件,执行mvn dependency:tree,查看依赖树。

  • dependencyManagement下的依赖定义,如果未用到,则不会被引入。

聚合关系

简单使用

通过modules/module标签指定一系列模块,聚合项目可以聚合一系列模块的构建。

<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>org.codehaus.mojo</groupId>
  <artifactId>my-parent</artifactId>
  <version>2.0</version>
  <packaging>pom</packaging>

  <modules>
    <module>my-project</module>
    <module>another-project</module>
    <module>third-project/pom-example.xml</module>
  </modules>
</project>

一个项目可以同时是父项目和聚合项目,也就是说,聚合项目可以被任何他所聚合的项目继承。也可以聚合不继承此项目的项目。

modules/module

模块的路径为相对路径。

properties

定义属性。采用占位符的方式${x},在poml.xml的任何位置访问,对于子项目可以从父项目中继承此属性。

构建配置

build

TODO 这里什么也没写...

Profile配置

profile

profile在settings.xml和pom.xml都有体现。POM4.0新加入的特性,根据不同环境提供不同的配置。

其中activation可以在指定的环境下修改pom定义,例如:

<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    ...
    <profiles>
        <profile>
            <id>test</id>
            <activation>
                <activeByDefault>false</activeByDefault>
                <jdk>1.5</jdk>
                <os>
                    <name>Windows XP</name>
                    <family>Windows</family>
                    <arch>x86</arch>
                    <version>5.1.2600</version>
                </os>
                <property>
                    <name>sparrow-type</name>
                    <value>African</value>
                </property>
                <file>
                    <exists>${basedir}/file2.properties</exists>
                    <missing>${basedir}/file1.properties</missing>
                </file>
            </activation>
            ...
        </profile>
    </profiles>
</project>

依赖管理

依赖是maven重要的一部分,前面提到了依赖、继承、聚合,涉及了项目与项目、模块与模块,依赖关系可能会非常复杂。

依赖冲突

A依赖B,B依赖C 1.0 版本,A依赖C 2.0版本,B依赖的C的依赖也会传递给A,那么同时引入C的两个版本就会出现依赖冲突。

flowchart TD
A(A) --> B(B)
B(B) --> C(C)
A(A) --> C(C)
A(A) -.传递依赖.-> C(C)

传递依赖可能导致,最终应用包中会引入具有相同 groupId 、 artifactId ,但版本号不同的jar,而同名类只会加载一次,类加载不知道从哪个jar包里加载(取决于依赖在依赖树中的位置),导致加载到错误的包,运行期间出现异常。

依赖调节机制

原则:

  • 路径最近优先

    A=>C 2.0版本 A=>B=>C 1.2版本,优先选择C 2.0版本

    flowchart TD
    A(A) --> B(B)
    B(B) --> C-v1.2(C-v1.2)
    A(A) --> C-v2.0(C-v2.0)
    
  • 最先声明有限

    如果A=>B=>X A=>D=>C路径一致,B先声明,则会使用C 1.2版本

flowchart TD
A(A) --> B(B)
A(A) --> D(D)
B(B) --> C-v1.2(C-v1.2)
D(D) --> C-v2.0(C-v2.0)
  • 同级依赖,后者覆盖前者

    下面展示了 urs-facade 两个版本先后声明,1.0.2在前1.0-SNAPSHOT在后,使用后声明的1.0-SNAPSHOT,反过来,如果后声明1.0.2,则使用1.0.2

    <dependencies>
      <dependency>
        <groupId>com.snb.urs</groupId>
        <artifactId>urs-facade</artifactId>
        <version>1.0.2</version>
      </dependency>
      <dependency>
        <groupId>com.snb.urs</groupId>
        <artifactId>urs-facade</artifactId>
        <version>1.0-SNAPSHOT</version>
      </dependency>
    </dependencies>
    

依赖检查

可使用mvn dependency:tree -Dverbose检查冲依赖。其中:

  • omitted for duplicate表示重复依赖,例:org.aspectj:aspectjweaver:jar:1.9.6:compile - omitted for duplicate
  • omitted for conflict with 下x.x.x,表示冲突依赖,例:org.slf4j:slf4j-api:jar:1.7.25:compile - omitted for conflict with 1.7.30
$ mvn dependency:tree -Dverbose
[INFO] Scanning for projects...
[INFO]
......
......
[INFO] online.xiyusu:springnote:war:0.0.1-SNAPSHOT
[INFO] +- online.xiyusu:tipbook-core:jar:1.0-SNAPSHOT:compile
[INFO] |  +- (org.springframework:spring-jdbc:jar:4.3.9.RELEASE:compile - omitted for duplicate)
[INFO] |  +- (org.aspectj:aspectjweaver:jar:1.9.6:compile - omitted for duplicate)
[INFO] |  +- (ch.qos.logback:logback-core:jar:1.2.3:compile - omitted for duplicate)
[INFO] |  +- (ch.qos.logback:logback-classic:jar:1.2.3:compile - omitted for duplicate)
[INFO] |  \- (org.slf4j:slf4j-api:jar:1.7.30:compile - omitted for duplicate)
[INFO] +- online.xiyusu:tipbook-test:jar:1.0-SNAPSHOT:compile
[INFO] |  +- (ch.qos.logback:logback-core:jar:1.2.3:compile - omitted for duplicate)
[INFO] |  +- (ch.qos.logback:logback-classic:jar:1.2.3:compile - omitted for duplicate)
[INFO] |  +- (org.slf4j:slf4j-api:jar:1.7.30:compile - omitted for duplicate)
[INFO] |  +- (org.springframework:spring-context:jar:4.3.9.RELEASE:compile - omitted for duplicate)
[INFO] |  +- (junit:junit:jar:4.12:compile - omitted for duplicate)
[INFO] |  \- (online.xiyusu:tipbook-core:jar:1.0-SNAPSHOT:compile - omitted for duplicate)
[INFO] +- org.springframework:spring-core:jar:4.3.9.RELEASE:compile
[INFO] |  \- (commons-logging:commons-logging:jar:1.2:compile - omitted for duplicate)
[INFO] +- org.springframework:spring-beans:jar:4.3.9.RELEASE:compile
[INFO] |  \- (org.springframework:spring-core:jar:4.3.9.RELEASE:compile - omitted for duplicate)
[INFO] +- org.springframework:spring-context:jar:4.3.9.RELEASE:compile
[INFO] |  +- org.springframework:spring-aop:jar:4.3.9.RELEASE:compile
[INFO] |  |  +- (org.springframework:spring-beans:jar:4.3.9.RELEASE:compile - omitted for duplicate)
[INFO] |  |  \- (org.springframework:spring-core:jar:4.3.9.RELEASE:compile - omitted for duplicate)
[INFO] |  +- (org.springframework:spring-beans:jar:4.3.9.RELEASE:compile - omitted for duplicate)
[INFO] |  +- (org.springframework:spring-core:jar:4.3.9.RELEASE:compile - omitted for duplicate)
[INFO] |  \- org.springframework:spring-expression:jar:4.3.9.RELEASE:compile
[INFO] |     \- (org.springframework:spring-core:jar:4.3.9.RELEASE:compile - omitted for duplicate)
[INFO] +- org.springframework:spring-context-support:jar:4.3.9.RELEASE:compile
[INFO] |  +- (org.springframework:spring-beans:jar:4.3.9.RELEASE:compile - omitted for duplicate)
[INFO] |  +- (org.springframework:spring-context:jar:4.3.9.RELEASE:compile - omitted for duplicate)
[INFO] |  \- (org.springframework:spring-core:jar:4.3.9.RELEASE:compile - omitted for duplicate)
[INFO] +- org.springframework:spring-jdbc:jar:4.3.9.RELEASE:compile
[INFO] |  +- (org.springframework:spring-beans:jar:4.3.9.RELEASE:compile - omitted for duplicate)
[INFO] |  +- (org.springframework:spring-core:jar:4.3.9.RELEASE:compile - omitted for duplicate)
[INFO] |  \- org.springframework:spring-tx:jar:4.3.9.RELEASE:compile
[INFO] |     +- (org.springframework:spring-beans:jar:4.3.9.RELEASE:compile - omitted for duplicate)
[INFO] |     \- (org.springframework:spring-core:jar:4.3.9.RELEASE:compile - omitted for duplicate)
[INFO] +- org.springframework:spring-webmvc:jar:4.3.9.RELEASE:compile
[INFO] |  +- (org.springframework:spring-aop:jar:4.3.9.RELEASE:compile - omitted for duplicate)
[INFO] |  +- (org.springframework:spring-beans:jar:4.3.9.RELEASE:compile - omitted for duplicate)
[INFO] |  +- (org.springframework:spring-context:jar:4.3.9.RELEASE:compile - omitted for duplicate)
[INFO] |  +- (org.springframework:spring-core:jar:4.3.9.RELEASE:compile - omitted for duplicate)
[INFO] |  +- (org.springframework:spring-expression:jar:4.3.9.RELEASE:compile - omitted for duplicate)
[INFO] |  \- org.springframework:spring-web:jar:4.3.9.RELEASE:compile
[INFO] |     +- (org.springframework:spring-aop:jar:4.3.9.RELEASE:compile - omitted for duplicate)
[INFO] |     +- (org.springframework:spring-beans:jar:4.3.9.RELEASE:compile - omitted for duplicate)
[INFO] |     +- (org.springframework:spring-context:jar:4.3.9.RELEASE:compile - omitted for duplicate)
[INFO] |     \- (org.springframework:spring-core:jar:4.3.9.RELEASE:compile - omitted for duplicate)
[INFO] +- org.springframework:spring-test:jar:4.3.9.RELEASE:test
[INFO] |  \- (org.springframework:spring-core:jar:4.3.9.RELEASE:test - omitted for duplicate)
[INFO] +- org.aspectj:aspectjweaver:jar:1.9.6:compile
[INFO] +- mysql:mysql-connector-java:jar:8.0.12:compile
[INFO] |  \- com.google.protobuf:protobuf-java:jar:2.6.0:compile
[INFO] +- com.alibaba:druid:jar:1.2.5:compile
[INFO] +- org.apache.commons:commons-dbcp2:jar:2.5.0:compile
[INFO] |  +- org.apache.commons:commons-pool2:jar:2.6.0:compile
[INFO] |  \- (commons-logging:commons-logging:jar:1.2:compile - omitted for duplicate)
[INFO] +- commons-codec:commons-codec:jar:1.11:compile
[INFO] +- commons-logging:commons-logging:jar:1.2:compile
[INFO] +- javax.servlet:javax.servlet-api:jar:4.0.0:compile
[INFO] +- javax.servlet.jsp.jstl:jstl-api:jar:1.2:compile
[INFO] |  +- javax.servlet:servlet-api:jar:2.5:compile
[INFO] |  \- javax.servlet.jsp:jsp-api:jar:2.1:compile
[INFO] +- taglibs:standard:jar:1.1.2:compile
[INFO] +- org.freemarker:freemarker:jar:2.3.29:compile
[INFO] +- org.apache.kafka:kafka_2.13:jar:2.4.0:compile
[INFO] |  +- (org.apache.kafka:kafka-clients:jar:2.4.0:compile - omitted for duplicate)
[INFO] |  +- (com.fasterxml.jackson.core:jackson-databind:jar:2.10.0:compile - omitted for conflict with 2.10.1)
[INFO] |  +- com.fasterxml.jackson.module:jackson-module-scala_2.13:jar:2.10.0:compile
[INFO] |  |  +- (org.scala-lang:scala-library:jar:2.13.1:compile - omitted for duplicate)
[INFO] |  |  +- (com.fasterxml.jackson.core:jackson-core:jar:2.10.0:compile - omitted for duplicate)
[INFO] |  |  +- (com.fasterxml.jackson.core:jackson-annotations:jar:2.10.0:compile - omitted for duplicate)
[INFO] |  |  +- (com.fasterxml.jackson.core:jackson-databind:jar:2.10.0:compile - omitted for duplicate)
[INFO] |  |  \- com.fasterxml.jackson.module:jackson-module-paranamer:jar:2.10.0:compile
[INFO] |  |     +- (com.fasterxml.jackson.core:jackson-databind:jar:2.10.0:compile - omitted for duplicate)
[INFO] |  |     \- com.thoughtworks.paranamer:paranamer:jar:2.8:compile
[INFO] |  +- com.fasterxml.jackson.dataformat:jackson-dataformat-csv:jar:2.10.0:compile
[INFO] |  |  +- (com.fasterxml.jackson.core:jackson-databind:jar:2.10.0:compile - omitted for duplicate)
[INFO] |  |  +- (com.fasterxml.jackson.core:jackson-annotations:jar:2.10.0:compile - omitted for duplicate)
[INFO] |  |  \- (com.fasterxml.jackson.core:jackson-core:jar:2.10.0:compile - omitted for duplicate)
[INFO] |  +- com.fasterxml.jackson.datatype:jackson-datatype-jdk8:jar:2.10.0:compile
[INFO] |  |  +- (com.fasterxml.jackson.core:jackson-core:jar:2.10.0:compile - omitted for duplicate)
[INFO] |  |  \- (com.fasterxml.jackson.core:jackson-databind:jar:2.10.0:compile - omitted for duplicate)
[INFO] |  +- net.sf.jopt-simple:jopt-simple:jar:5.0.4:compile
[INFO] |  +- com.yammer.metrics:metrics-core:jar:2.2.0:compile
[INFO] |  |  \- (org.slf4j:slf4j-api:jar:1.7.2:compile - omitted for conflict with 1.7.30)
[INFO] |  +- org.scala-lang.modules:scala-collection-compat_2.13:jar:2.1.2:compile
[INFO] |  |  \- (org.scala-lang:scala-library:jar:2.13.0:compile - omitted for conflict with 2.13.1)
[INFO] |  +- org.scala-lang.modules:scala-java8-compat_2.13:jar:0.9.0:compile
[INFO] |  |  \- (org.scala-lang:scala-library:jar:2.13.0:compile - omitted for conflict with 2.13.1)
[INFO] |  +- org.scala-lang:scala-library:jar:2.13.1:compile
[INFO] |  +- org.scala-lang:scala-reflect:jar:2.13.1:compile
[INFO] |  |  \- (org.scala-lang:scala-library:jar:2.13.1:compile - omitted for duplicate)
[INFO] |  +- com.typesafe.scala-logging:scala-logging_2.13:jar:3.9.2:compile
[INFO] |  |  +- (org.scala-lang:scala-library:jar:2.13.0:compile - omitted for conflict with 2.13.1)
[INFO] |  |  +- (org.scala-lang:scala-reflect:jar:2.13.0:compile - omitted for conflict with 2.13.1)
[INFO] |  |  \- (org.slf4j:slf4j-api:jar:1.7.26:compile - omitted for conflict with 1.7.30)
[INFO] |  +- (org.slf4j:slf4j-api:jar:1.7.28:compile - omitted for conflict with 1.7.30)
[INFO] |  +- org.apache.zookeeper:zookeeper:jar:3.5.6:compile
[INFO] |  |  +- org.apache.zookeeper:zookeeper-jute:jar:3.5.6:compile
[INFO] |  |  |  \- (org.apache.yetus:audience-annotations:jar:0.5.0:compile - omitted for duplicate)
[INFO] |  |  +- org.apache.yetus:audience-annotations:jar:0.5.0:compile
[INFO] |  |  +- io.netty:netty-handler:jar:4.1.42.Final:compile
[INFO] |  |  |  +- io.netty:netty-common:jar:4.1.42.Final:compile
[INFO] |  |  |  +- io.netty:netty-buffer:jar:4.1.42.Final:compile
[INFO] |  |  |  |  \- (io.netty:netty-common:jar:4.1.42.Final:compile - omitted for duplicate)
[INFO] |  |  |  +- io.netty:netty-transport:jar:4.1.42.Final:compile
[INFO] |  |  |  |  +- (io.netty:netty-common:jar:4.1.42.Final:compile - omitted for duplicate)
[INFO] |  |  |  |  +- (io.netty:netty-buffer:jar:4.1.42.Final:compile - omitted for duplicate)
[INFO] |  |  |  |  \- io.netty:netty-resolver:jar:4.1.42.Final:compile
[INFO] |  |  |  |     \- (io.netty:netty-common:jar:4.1.42.Final:compile - omitted for duplicate)
[INFO] |  |  |  \- io.netty:netty-codec:jar:4.1.42.Final:compile
[INFO] |  |  |     +- (io.netty:netty-common:jar:4.1.42.Final:compile - omitted for duplicate)
[INFO] |  |  |     +- (io.netty:netty-buffer:jar:4.1.42.Final:compile - omitted for duplicate)
[INFO] |  |  |     \- (io.netty:netty-transport:jar:4.1.42.Final:compile - omitted for duplicate)
[INFO] |  |  +- io.netty:netty-transport-native-epoll:jar:4.1.42.Final:compile
[INFO] |  |  |  +- (io.netty:netty-common:jar:4.1.42.Final:compile - omitted for duplicate)
[INFO] |  |  |  +- (io.netty:netty-buffer:jar:4.1.42.Final:compile - omitted for duplicate)
[INFO] |  |  |  +- (io.netty:netty-transport:jar:4.1.42.Final:compile - omitted for duplicate)
[INFO] |  |  |  \- io.netty:netty-transport-native-unix-common:jar:4.1.42.Final:compile
[INFO] |  |  |     +- (io.netty:netty-common:jar:4.1.42.Final:compile - omitted for duplicate)
[INFO] |  |  |     +- (io.netty:netty-buffer:jar:4.1.42.Final:compile - omitted for duplicate)
[INFO] |  |  |     \- (io.netty:netty-transport:jar:4.1.42.Final:compile - omitted for duplicate)
[INFO] |  |  \- (org.slf4j:slf4j-api:jar:1.7.25:compile - omitted for conflict with 1.7.30)
[INFO] |  \- commons-cli:commons-cli:jar:1.4:compile
[INFO] +- org.apache.kafka:kafka-clients:jar:2.4.0:compile
[INFO] |  +- com.github.luben:zstd-jni:jar:1.4.3-1:compile
[INFO] |  +- org.lz4:lz4-java:jar:1.6.0:compile
[INFO] |  +- org.xerial.snappy:snappy-java:jar:1.1.7.3:compile
[INFO] |  \- (org.slf4j:slf4j-api:jar:1.7.28:compile - omitted for conflict with 1.7.30)
[INFO] +- com.fasterxml.jackson.core:jackson-core:jar:2.10.1:compile
[INFO] +- com.fasterxml.jackson.core:jackson-databind:jar:2.10.1:compile
[INFO] |  +- (com.fasterxml.jackson.core:jackson-annotations:jar:2.10.1:compile - omitted for duplicate)
[INFO] |  \- (com.fasterxml.jackson.core:jackson-core:jar:2.10.1:compile - omitted for duplicate)
[INFO] +- com.fasterxml.jackson.core:jackson-annotations:jar:2.10.1:compile
[INFO] +- ch.qos.logback:logback-core:jar:1.2.3:compile
[INFO] +- ch.qos.logback:logback-classic:jar:1.2.3:compile
[INFO] |  +- (ch.qos.logback:logback-core:jar:1.2.3:compile - omitted for duplicate)
[INFO] |  \- (org.slf4j:slf4j-api:jar:1.7.25:compile - omitted for conflict with 1.7.30)
[INFO] +- org.slf4j:slf4j-api:jar:1.7.30:compile
[INFO] +- junit:junit:jar:4.12:test (scope not updated to compile)
[INFO] |  \- org.hamcrest:hamcrest-core:jar:1.3:test
[INFO] \- org.testng:testng:jar:6.14.3:test
[INFO]    +- com.beust:jcommander:jar:1.72:test
[INFO]    \- org.apache-extras.beanshell:bsh:jar:2.0b6:test
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  19.488 s
[INFO] Finished at: 2022-02-18T01:23:35+08:00
[INFO] ------------------------------------------------------------------------

依赖调整

  1. 根据dependencies/dependency中的scope调整。
  2. 根据dependencies/dependency中的optional,将依赖设置为可选依赖。
  3. 根据exlcusions/exlcusion进行排包(主要方法)。

版本及快照

快照是某一时间点的项目进度或者版本。

在正常项目开发过程中,开发阶段项目内容处于不稳定状态,项目版本不断迭代,一个项目A依赖另一个项目B,项目B不断更新依赖包,并发到仓库中,于此同时项目A就要不断更新B项目的依赖,不断修改版本号造成了人员浪费。maven提供的快照解决了者一问题。需注意:

  • 快照版本是以-SNAPSHOT结尾的版本。
  • 与快照版本对应的是RELEASE,发布版本或者正式版本,非快照版本即为正式版本。
  • 快照版本在deploy时可以覆盖远程仓库版本,本地打包引用依赖时可以获取最新的快照版本,而不需要修改版本号。
  • 正常远程仓库可设置正式版是否允许覆盖,一般来说远程仓库正式版本不允许覆盖,如有更新需升级版本号。
  • 快照版本由于可覆盖特性,如果在生产环境使用,容易出现风险,将测试代码发布到生产,因此生产环境要求使用正式版本。

构建生命周期

生命周期

maven构建生命周期(Lifecycle)有三个生命周期defaultcleansite

  • default 生命周期进行项目部署
  • clean 生命周期进行项目清理
  • site 生命周期进行项目站点创建

构建阶段

构建生命周期(Lifecycle)由一组构建阶段(Phase)组成。

插件目标

构建阶段(Phase)由一组插件目标(goal)组成。

插件目标是一个特定的任务,比构件阶段更加精细化。可以绑定零个或多个构建阶段,未绑定构建阶段的目标可以在构建生命周期之外执行,执行顺序取决于调用目标和构建阶段。例如:dependency:copy dependencies,下面的示例,先执行clean 阶段,然后是dependency:copy dependencies目标,最后执行package

mvn clean dependency:copy dependencies package

如果插件目标被绑定在构件阶段,那么在这些阶段对应执行。

详述生命周期

Clean Lifecycle

阶段描述
pre-clean 执行项目清理前所需要的流程。
clean 移除所有之前生成的文件
post-clean 执行项目清理后所需要的流程。

Default Lifecycle

主要完成校验项目、编译资源、测试、打包生成二进制文件(jar等)、集成测试、安装包到本地目录、部署已安装的包到远程仓库。

构建阶段
阶段描述
validate 验证项目是正确的并且所有必须信息是可用的。
initialize initialize build state, e.g. set properties or create directories.
generate-sources generate any source code for inclusion in compilation.
process-sources process the source code, for example to filter any values.
generate-resources generate resources for inclusion in the package.
process-resources copy and process the resources into the destination directory, ready for packaging.
compile 编译项目源码
process-classes post-process the generated files from compilation, for example to do bytecode enhancement on Java classes.
generate-test-sources generate any test source code for inclusion in compilation.
process-test-sources process the test source code, for example to filter any values.
generate-test-resources create resources for testing.
process-test-resources copy and process the resources into the test destination directory.
test-compile compile the test source code into the test destination directory
process-test-classes post-process the generated files from test compilation, for example to do bytecode enhancement on Java classes.
test 使用合适的单元测试框架执行测试。测试不要求打包和部署代码。Junit等。
prepare-package perform any operations necessary to prepare a package before the actual packaging. This often results in an unpacked, processed version of the package.
package 将编译好的源码打包,一般会生成在项目下的target目录
pre-integration-test perform actions required before integration tests are executed. This may involve things such as setting up the required environment.
integration-test process and deploy the package if necessary into an environment where integration tests can be run.
post-integration-test perform actions required after integration tests have been executed. This may including cleaning up the environment.
verify 检查确认包是合法且符合质量标准的。
install 将包安装到本地,作为本地其他项目的依赖项。
deploy 将包发布到远程仓库,供其他开发者和项目使用。
package、install、deploy

package 打包到项目target目录;

install 打包到项目target目录、本地仓库;

deploy 打包到项目target目录、本地仓库、远程仓库;

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

$ mvn clean package
[INFO] Scanning for projects...
[INFO]
[INFO] ----------------------< com.mycompany.app:my-app >----------------------
[INFO] Building my-app 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- `maven-clean-plugin:3.1.0:clean` (default-clean) @ my-app ---
[INFO] Deleting D:\workspace\tmp\my-app\target
[INFO]
[INFO] --- `maven-resources-plugin:3.0.2:resources` (default-resources) @ my-app ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory D:\workspace\tmp\my-app\src\main\resources
[INFO]
[INFO] --- `maven-compiler-plugin:3.8.0:compile` (default-compile) @ my-app ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to D:\workspace\tmp\my-app\target\classes
[INFO]
[INFO] --- `maven-resources-plugin:3.0.2:testResources` (default-testResources) @ my-app ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory D:\workspace\tmp\my-app\src\test\resources
[INFO]
[INFO] --- `maven-compiler-plugin:3.8.0:testCompile` (default-testCompile) @ my-app ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to D:\workspace\tmp\my-app\target\test-classes
[INFO]
[INFO] --- `maven-surefire-plugin:2.22.1:test` (default-test) @ my-app ---
[INFO]
[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.mycompany.app.AppTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.016 s - in com.mycompany.app.AppTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO]
[INFO] --- maven-jar-plugin:3.0.2:jar (default-jar) @ my-app ---
[INFO] Building jar: D:\workspace\tmp\my-app\target\my-app-1.0-SNAPSHOT.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  1.981 s
[INFO] Finished at: 2022-03-12T18:14:58+08:00
[INFO] ------------------------------------------------------------------------

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

$ mvn clean install
[INFO] Scanning for projects...
[INFO]
[INFO] ----------------------< com.mycompany.app:my-app >----------------------
[INFO] Building my-app 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- `maven-clean-plugin:3.1.0:clean` (default-clean) @ my-app ---
[INFO] Deleting D:\workspace\tmp\my-app\target
[INFO]
[INFO] --- `maven-resources-plugin:3.0.2:resources` (default-resources) @ my-app ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory D:\workspace\tmp\my-app\src\main\resources
[INFO]
[INFO] --- `maven-compiler-plugin:3.8.0:compile` (default-compile) @ my-app ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to D:\workspace\tmp\my-app\target\classes
[INFO]
[INFO] --- `maven-resources-plugin:3.0.2:testResources` (default-testResources) @ my-app ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory D:\workspace\tmp\my-app\src\test\resources
[INFO]
[INFO] --- `maven-compiler-plugin:3.8.0:testCompile` (default-testCompile) @ my-app ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to D:\workspace\tmp\my-app\target\test-classes
[INFO]
[INFO] --- `maven-surefire-plugin:2.22.1:test` (default-test) @ my-app ---
[INFO]
[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.mycompany.app.AppTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.032 s - in com.mycompany.app.AppTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO]
[INFO] --- `maven-jar-plugin:3.0.2:jar` (default-jar) @ my-app ---
[INFO] Building jar: D:\workspace\tmp\my-app\target\my-app-1.0-SNAPSHOT.jar
[INFO]
[INFO] --- `maven-install-plugin:2.5.2:install` (default-install) @ my-app ---
[INFO] Installing D:\workspace\tmp\my-app\target\my-app-1.0-SNAPSHOT.jar to D:\develop\maven\repository\com\mycompany\app\my-app\1.0-SNAPSHOT\my-app-1.0-SNAPSHOT.jar
[INFO] Installing D:\workspace\tmp\my-app\pom.xml to D:\develop\maven\repository\com\mycompany\app\my-app\1.0-SNAPSHOT\my-app-1.0-SNAPSHOT.pom
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  2.047 s
[INFO] Finished at: 2022-03-12T18:16:43+08:00
[INFO] ------------------------------------------------------------------------

mvn clean deploy 依次执行了clean、resources、compile、testResources、testCompile、test、jar、install、deploy9个阶段。

$ mvn clean deploy
[INFO] Scanning for projects...
[INFO]
[INFO] ----------------------< com.mycompany.app:my-app >----------------------
[INFO] Building my-app 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- `maven-clean-plugin:3.1.0:clean` (default-clean) @ my-app ---
[INFO] Deleting D:\workspace\tmp\my-app\target
[INFO]
[INFO] --- `maven-resources-plugin:3.0.2:resources` (default-resources) @ my-app ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory D:\workspace\tmp\my-app\src\main\resources
[INFO]
[INFO] --- `maven-compiler-plugin:3.8.0:compile` (default-compile) @ my-app ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to D:\workspace\tmp\my-app\target\classes
[INFO]
[INFO] --- `maven-resources-plugin:3.0.2:testResources ``(default-testResources) @ my-app ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory D:\workspace\tmp\my-app\src\test\resources
[INFO]
[INFO] --- `maven-compiler-plugin:3.8.0:testCompile` (default-testCompile) @ my-app ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to D:\workspace\tmp\my-app\target\test-classes
[INFO]
[INFO] --- `maven-surefire-plugin:2.22.1:test` (default-test) @ my-app ---
[INFO]
[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.mycompany.app.AppTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.016 s - in com.mycompany.app.AppTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO]
[INFO] --- `maven-jar-plugin:3.0.2:jar` (default-jar) @ my-app ---
[INFO] Building jar: D:\workspace\tmp\my-app\target\my-app-1.0-SNAPSHOT.jar
[INFO]
[INFO] --- `maven-install-plugin:2.5.2:install` (default-install) @ my-app ---
[INFO] Installing D:\workspace\tmp\my-app\target\my-app-1.0-SNAPSHOT.jar to D:\develop\maven\repository\com\mycompany\app\my-app\1.0-SNAPSHOT\my-app-1.0-SNAPSHOT.jar
[INFO] Installing D:\workspace\tmp\my-app\pom.xml to D:\develop\maven\repository\com\mycompany\app\my-app\1.0-SNAPSHOT\my-app-1.0-SNAPSHOT.pom
[INFO]
[INFO] --- `maven-deploy-plugin:2.8.2:deploy` (default-deploy) @ my-app ---
[INFO] ------------------------------------------------------------------------
......

Site Lifecycle

阶段描述
pre-site execute processes needed prior to the actual project site generation
site generate the project's site documentation
post-site execute processes needed to finalize the site generation, and to prepare for site deployment
site-deploy deploy the generated site documentation to the specified web server
站点

以web形式展示项目信息

$ mvn site

语法规则

mvn Phase plugin:goal

仓库

早期的jar包管理,可能就放在项目lib下,也可能放在svn上。maven提供了仓库的概念。

仓库是maven中存储管理JAR包的地方,可以分为本地仓库、远程仓库(包括中央仓库、其他第三方仓库、局域网仓库),远程仓库提供了依赖包的上传及下载功能 。

本地仓库

本地存储JAR包的目录,是maven依赖包获取目录。maven项目构建时,会从远程仓库拉取项目依赖的JAR包。本地仓库包含了从远程仓库拉取的依赖包、也包括本地构建生成的依赖包,本地构建生成的包属于未发布的临时包。本地仓库的包可随时被覆盖,关于maven构建命令参考 构建生命周期

<settings>
	<localRepository>D:/localRepository</localRepository>
</settings>

远程仓库

远程仓库是指不在本机的仓库,可通过一系列网络协议远程访问。其中由maven社区维护的仓库叫中央仓库,由其他公司或社区维护的仓库,对外提供依赖下载服务为第三方仓库,如阿里镜像仓库、华为镜像仓库等。还有一部分仓库也是由公司维护,但仅限于对内部提供依赖下载及私有依赖的管理。

<repositories>
    <repository>
      <id>my-repo1</id>
      <name>your custom repo</name>
      <url>http://jarsm2.dyndns.dk</url>
    </repository>
    <repository>
      <id>my-repo2</id>
      <name>your custom repo</name>
      <url>http://jarsm2.dyndns.dk</url>
    </repository>
</repositories>

局域网的仓库,可通过nexus搭建。

仓库配置

全局配置

配置默认路径:${maven.home}/conf/settings.xml,其中${maven.home}指maven的安装目录。

<settings>
	<mirrors>
		<mirror>
			<id>nexus</id>
			<mirrorOf>*</mirrorOf>
			<url>
				http://10.0.128.16:8081/nexus/content/groups/public/
			</url>
		</mirror>
	</mirrors>
</settings>

用户配置

配置默认路径:${user.home}/.m2/settings.xml,其中${user.home}指用户目录。

<settings>
	<mirrors>
		<mirror>
			<id>nexus</id>
			<mirrorOf>*</mirrorOf>
			<url>
				http://10.0.128.16:8081/nexus/content/groups/public/
			</url>
		</mirror>
	</mirrors>
</settings>

自定义配置

在项目下的pom.xml中配置仓库

<project>
...
  <repositories>
    <repository>
      <id>my-repo1</id>
      <name>your custom repo</name>
      <url>http://jarsm2.dyndns.dk</url>
    </repository>
    <repository>
      <id>my-repo2</id>
      <name>your custom repo</name>
      <url>http://jarsm2.dyndns.dk</url>
    </repository>
  </repositories>
...
</project>

settings.xml

maven使用了镜像(mirror),镜像仓库可以更快的同步、自由控制等。

mirrors下可以匹配多个镜像仓库,但是maven并不会聚合这些镜像,只会选择第一个匹配的。

mirrorOf 目的时拦截对远程仓库的请求。

  • *表示匹配所有镜像,意思时所有请求都会重定向到这个镜像所对应的url
  • external:*匹配所有非本地和文件协议的
  • repo,repo1匹配 repo 或者 repo1
  • *,!repo1匹配除了repo1

仓库关系

开放服务的第三方仓库有很多,如阿里仓库、华为仓库等。仓库可以通过https协议进行同步。

可以是这样(当然某些私服可能不与外部交互,不做同步需要,无源码的需要人工上传包):

flowchart TD
中央仓库(中央仓库) --> 远程仓库1(阿里镜像仓库)
中央仓库(中央仓库) --> 远程仓库2(华为镜像仓库)
中央仓库(中央仓库) --> 远程仓库3(网易镜像仓库)
远程仓库1(阿里镜像仓库) .-> 远程仓库(某私服仓库) 
远程仓库2(华为镜像仓库) .-> 远程仓库(某私服仓库) 
远程仓库3(网易镜像仓库) .-> 远程仓库(某私服仓库) 
subgraph 某银行
 远程仓库(某私服仓库)  --> 本地仓库1(开发本地仓库1)
 远程仓库(某私服仓库)  --> 本地仓库2(开发本地仓库2)
 远程仓库(某私服仓库)  --> 本地仓库3(开发本地仓库3)
end

也可以是这样(这中时个人开发者,会自行选择速度较快的仓库):

flowchart TD
中央仓库(中央仓库) --> 远程仓库1(阿里镜像仓库)
中央仓库(中央仓库) --> 远程仓库2(华为镜像仓库)
中央仓库(中央仓库) --> 远程仓库3(网易镜像仓库)
远程仓库1(阿里镜像仓库) .-> 本地仓库(本地仓库) 
远程仓库2(华为镜像仓库) .-> 本地仓库(本地仓库) 
远程仓库3(网易镜像仓库) .-> 本地仓库(本地仓库) 

仓库优先级

Remote repository URLs are queried in the following order for artifacts until one returns a valid result:

  1. effective settings:
    1. Global settings.xml
    2. User settings.xml
  2. local effective build POM:
    1. Local pom.xml
    2. Parent POMs, recursively
    3. Super POM
  3. effective POMs from dependency path to the artifact.

For each of these locations, the repositories within the profiles are queried first in the order outlined at Introduction to build profiles.

远程仓库URL查找优先级:

全局配置文件>用户配置文件>pom.xml>父级pom.xml>顶层 pom.xml>依赖中的 pom. xml

上述配置中,profile下的仓库被优先查找。

其他内容

核心存款系统pom.xml文件,参考附录[核心存款系统集成项目pom.xml](# 核心存款系统集成项目pom.xml)

插件

maven本质是个插件执行框架。

maven及第三方提供的插件,可以参考maven.apache.org/plugins/ind…

常见的插件

maven-archetype-plugin

原型插件,用来根据原型模板创建项目。

前面创建项目我们就是用的原型插件,需要调用mvn archetype:generate目标。

$ mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=my-app -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.4 -DinteractiveMode=false

maven-jar-plugin

maven-war-plugin

maven-assembly-plugin

maven-jetty-plugin

<plugin>
    <groupId>org.eclipse.jetty</groupId>
    <artifactId>jetty-maven-plugin</artifactId>
    <version>9.4.20.v20190813</version>
    <configuration>
        <scanIntervalSeconds>10</scanIntervalSeconds>
        <webApp>
            <contextPath>/note</contextPath>
        </webApp>
    </configuration>
</plugin>

推荐

pom.xml标签大全:菜鸟教程

写在最后

maven 知识点很多,本文只得皮毛,后续不定时补充。