@TOC
一、依赖管理
上一篇我们说到了依赖,下来我们继续看依赖管理。
POM 的元素包含可以被其他项目使用的声明。这样的 POM 的子项目将会自动继承这些声明。其他项目可以通过使用元素的 import值来导入它们。引用了dependencyManagement元素的项目可以使用它所声明的依赖,而不需要指定它们的version坐标。如果dependencyManagement中的在稍后有所改变,则它将被所有引用它的 POM 拾起
举个例子:
<properties>
<netty.version>4.1.9</netty.version>
...
...
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>${
netty.version}</version>
</dependency>
</dependencies>
...
</dependencyManagement>
对于这种使用场景,依赖的元素有一个特殊的 import 值:它将把外部 POM(没有被声明为parent)的dependencyManagement元素的内容导入到当前 POM 的dependencyManagement元素中。
二、构建的生命周期
Maven 构建的生命周期是一个明确定义的用于构建和分发构件的过程。有 3 个内置的构建生命周期:clean、default 和 site。
一个构建的生命周期由一系列的阶段所组成。下面是默认的构建生命周期的各个阶段的一个部分清单。
- validate——检查项目是否正确,所有必需的信息是否已经就绪。
- process-sources——处理源代码,如过滤任何值。
- compile——编译项目的源代码。
- process-test-resources——复制并处理资源到测试目标目录中。
- test-compile——将测试源代码编译到测试目标目录中。
- test——使用合适的单元测试框架测试编译的源代码。
- package——将编译的代码打包为它的可分发格式,如 JAR。
- integration-test——处理并将软件包部署到一个可以运行集成测试的环境中。
- verify——运行任何的检查以验证软件包是否有效,并且符合质量标准。
- install——将软件包安装到本地存储库中,在那里其他本地构建项目可以将它引用为依赖。
- deploy——将最终的构件上传到远程存储库,以与其他开发人员和项目共享。
执行这些阶段中的一个阶段将会调用所有前面的阶段。例如:
mvn package;
将会执行 validate、compile 以及 test,并随后将该构件组装到该项目的目标目录中。执行:
mvn clean install
将会首先移除所有先前的构建所创建的结果。然后,它将会运行所有到该阶段的默认阶段,并且包括将该构件放置到你的本地存储库的文件系统中。
三、插件
虽然Maven协调了所有构建生命周期阶段的执行,但是它并没有直接实现它们,相反,它将它们委托给了插件
阶段,这些插件是maven-plugin类型的构件(打包为JAR文件 )。Apache Maven项目为标准构建生命周期所定义的所有任务都提供了插件,更多的是由第三方生产的,用于处理各种自定义的任务。
插件可能拥有多个内部步骤,或者目标,其也可以被单独调用。例如,在一个 JAR 项目中,默认的构建生命周期由 maven-jar-plugin 处理,其将构建的各个阶段映射到了它自己的以及其他插件的目标中,如表 所示。
|阶 段|插件目标 |
|--|--|
| process-resources | resources:resources|
|compile|compiler:compiler|
|process-test-resources|resources:testResources|
|test-compile|compiler:testCompile|
|test |surefire:test|
|package|jar:jar|
|install|install:install|
|deploy|deploy:deploy|
四、插件管理
如同dependencyManagement,pluginManagement声明了其他 POM 可以使用的信息。但是这只适用于子POM,因为对于插件来说,没有导入声明就和依赖一样,version坐标是继承的。
例如:
<build>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
</plugin>
</plugins>
</pluginManagement>
</build>
下面展示上面这个代码中的 POM 片段的子 POM 是如何使用其父 POM 的pluginManagement配置的,它只引用了其构建所需的插件。子 POM 还可以重写它需要自定义的任何插件配置。
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
五、存储库
Maven的构件存储库 可能是远程的,也可能是本地的。
- 远程存储库是一个 Maven 从其下载 POM 文件中所引用的依赖的服务。如果你有上传权限,那么这些依赖中可能也会包含由你自己的项目所产生的构件。大量开放源代码的Maven 项目(包含 Netty)都将它们的构件发布到可以公开访问的 Maven 存储库。
本地存储库是一个本地的目录,其包含从远程存储库下载的构件,以及你在本地机器上
构建并安装的构件。它通常放在你的主目录下,如:> C:\Users\maw\.m2\repository
Maven 存储库的物理目录结构使用 GAV 坐标,如同 Java 编译器使用包名一样。例如,在Maven 下载了下面的依赖之后:
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.9.Final</version>
</dependency>
将会在本地存储库中找到以下内容:
.m2\repository
|---\io
|---\netty
|---\netty-all
|---\4.1.9.Final
netty-all-4.1.9.Final.jar
netty-all-4.1.9.Final.jar.sha1
netty-all-4.1.9.Final.pom
netty-all-4.1.9.Final.pom.sha1
_maven.repositories
六、快照和发布
远程存储库通常会为正在开发的构件,以及那些稳定发布或者生产发布的构件,定义不同的区域。这些区域被分别称为快照存储库和发布存储库。
快照: 一个version值由-SNAPSHOT 结尾的构件将被认为是还没有发布的。这种构件可以重复地使用相同的version值被上传到存储库。每次它都会被分配一个唯一的时间戳。当项目检索构件时,下载的是最新实例。
发布: 一个version值不具有-SNAPSHOT 后缀的构件将会被认为是一个发布版本。通常,存储库策略只允某一特定的发布版本上传一次。
当构建一个具有 SNAPSHOT 依赖的项目时,Maven 将检查本地存储库中是否有对应的副本。如果没有,它将尝试从指定的远程存储库中检索,在这种情况下,它将接收到具有最新时间戳的构件。如果本地的确有这个构件,并且当前构建也是这一天中的第一个,那么 Maven 将默认尝试更新该本地副本。这个行为可以通过使用 Maven 配置文件(settings.xml)中的配置或者命令行标志来进行配置。
七、POM 的继承和聚合
1.POM 继承
POM 文件可能包含子项目要继承(并可能重写)的信息。
2.POM 聚合
聚合器 POM 会构建一个或者多个子项目,这些子项目驻留在该 POM 所在目录的子目录中。子项目,或者标签,是由它们的目录名标识的:
<modules>
<module>Server</module>
<module>Client</module>
</modules>
当构建子项目时,Maven 将创建一个 reactor,它将计算存在于它们之间的任何依赖,以确定它们必须遵照的构建顺序。注意,聚合器 POM 不一定是它声明为模块的项目的父 POM。(每个子项目都可以声明一个不同 POM 作为它的parent元素的值。)