Maven生命周期
之前我们在命令行中使用的第二个命令是:mvn package。这里的package是一个maven的生命周期阶段
(lifecycle phase )。生命周期指项目的构建过程,它包含了一系列的有序的阶段 (phase),而一个阶段就是构建过程
中的一个步骤。
一个完整的项目构建过程通常包括清理、编译、测试、打包、集成测试、验证、部署等步骤,Maven从中抽取了
一套完善的、易扩展的生命周期。Maven的生命周期是抽象的,其中的具体任务都交由插件来完成。Maven为大多
数构建任务编写并绑定了默认的插件,如针对编译的插件:maven-compiler-plugin。用户也可自行配置或编写插
件。
那么生命周期阶段和上面说的插件目标之间是什么关系呢?插件目标可以绑定到生命周期阶段上。一个生命周期
阶段可以绑定多个插件目标。当maven在构建过程中逐步的通过每个阶段时,会执行该阶段所有的插件目标。
maven能支持不同的生命周期,但是最常用的是默认的Maven生命周期 (default Maven lifecycle )。Maven定
义了三套生命周期:clean、default、site,每个生命周期都包含了一些阶段(phase)。三套生命周期相互独立,但
各个生命周期中的phase却是有顺序的,且后面的phase依赖于前面的phase。执行某个phase时,其前面的phase会
依顺序执行,但不会触发另外两套生命周期中的任何phase。
clean生命周期
clean生命周期主要的目的是清理项目,包括以下三个阶段:
1.pre-clean :执行清理前的工作;
2.clean :清理上一次构建生成的所有文件;
3.post-clean :执行清理后的工作
default生命周期
default生命周期是最核心的,它包含了构建项目时真正需要执行的所有步骤:
1.validate
2.initialize
3.generate-sources
4.process-sources :处理项目主资源文件。一般来说,是对src/main/resources目录的内容进行变量替换等
工作后,复制到项目输出的主classpath目录中
5.generate-resources
6.process-resources :复制和处理资源文件到target目录,准备打包;
7.compile :编译项目的源代码,一般来说,是编译src/main/Java目录下的Java文件至项目输出的主
classpath目录中;
8.process-classes
9.generate-test-sources
10.process-test-sources :处理项目测试资源文件。一般来说,是对src/test/resources目录的内容进行变量
替换等工作后,复制到项目输出的测试classpath目录中;
11.generate-test-resources
12.process-test-resources
13.test-compile :编译项目的测试代码,一般来说,是编译src/test/java目录下的Java文件至项目输出的测
试classpath目录中;
14.process-test-classes
15.test :使用单元测试框架运行测试,测试代码不会打包或部署;
16.prepare-package
17.package :接受编译好的代码,打包成jar或者war或者其他格式的分发包;
18.pre-integration-test
19.integration-test
20.post-integration-test
21.verify
22.install :将包安装到Maven本地仓库,供本地其他Maven项目使用
23.deploy :将最终的包复制到远程仓库,供其他开发人员和Maven项目使用
site生命周期
site生命周期是建立和发布项目站点,Maven能够基于POM所包含的信息,自动生成站点。它包含四个阶段:
1.pre-site :在生成项目站点前要完成的工作;
2.site :生成项目的站点文档;
3.post-site :在生成项目站点后要完成的工作;
4.site-deploy :发布生成的站点文档;
Maven的生命周期的各个阶段是前后阶段相互依赖的,当用户调用clean的时候,pre-clean 和 clean阶段会顺序
执行,不会碰触default的任何阶段。
在命令行中的复杂调用和生命周期各个阶段的执行情况,从三个例子来说明:
mvn test
该命令调用default生命周期的test阶段。实际执行的阶段为default生命周期的validate到test的所有阶段。
mvn clean install
该命令调用clean生命周期的clean阶段和default生命周期的install阶段。实际执行的是clean生命周期的pre-
clean、clean阶段和default生命周期的validate到install的所有阶段。该命令结合了两个生命周期,是执行真正项目
构建之前清理项目的一个很好的实践。
mvn clean deploy site-deploy : 该命令调用了clean生命周期的clean阶段和default生命周期的deploy阶段,
以及site生命周期的site-deploy阶段。实际执行的是clean生命周期的pre-clean、clean阶段和default生命周期的所
有阶段,以及site生命周期的所有阶段。
Maven的插件
之前我们用了mvn archetype:generate命令来生成一个项目。那么这里的 archetype:generate 是什么意思呢?
archetype是一个插件的名字,generate是目标(goal)的名字。这个命令的意思是告诉maven执行archetype插件的
generate目标。
一个目标是一个工作单元,而插件则是一个或者多个目标的集合。比如说Jar插件,Compiler插件,Surefire插件
等。从看名字就能知道,Jar插件包含建立Jar文件的目标, Compiler插件包含编译源代码和单元测试代码的目标。
Surefire插件的话,则是运行单元测试。
看到这里,估计你能明白了,mvn本身不会做太多的事情,它不知道怎么样编译或者怎么样打包。它把构建的任
务交给插件去做。插件定义了常用的构建逻辑,能够被重复利用。这样做的好处是,一旦插件有了更新,那么所有的
maven用户都能得到更新。
Maven的核心分发包只有不到3MB的大小,Maven会在需要的时候下载并使用插件,对于插件本身,为了能够
复用代码,它往往能够完成多个任务。Maven的生命周期与插件相互绑定,用以完成实际的构建任务。具体而言是生
命周期的阶段与插件的目标相互绑定,以完成某个具体的构建任务。
Maven的核心文件很小,主要的任务都是由插件来完成。定位到:%本地仓库%\org\apache\maven\plugins,
可以看到一些下载好的插件:
Maven官网上有更详细的官方插件列表:
查看更多的插件参考:http://maven.apache.org/plugins/index.html
内置绑定
Maven在核心为一些主要的生命周期阶段绑定了很多插件的目标。
clean生命周期阶段与插件目标的绑定关系:
default生命周期与内置插件绑定关系及具体任务(打包类型: jar):
site生命周期阶段与插件目标的绑定关系:
自定义绑定
用户可以根据需要将任何插件目标绑定到任何生命周期的阶段,如:将maven-source-plugin的jar-no-fork目
标绑定到default生命周期的package阶段,这样,以后在执行mvn package命令打包项目时,在package阶段之后
会执行源代码打包,生成如:hi-0.0.1-SNAPSHOT-sources.jar形式的源码包。
新建的hi项目:
我们在hi项目中的pom.xml配置文件中加入如下代码:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
我们右击项目名字,选择Run As,再次选择Maven Build选项
在出现的窗口中的Goals处的输入框中输入:package,最后点击Run
控制台输出成功的是:
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building hi 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ hi ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory E:\Java\JavaEE\Demo\hi\src\main\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ hi ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to E:\Java\JavaEE\Demo\hi\target\classes
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ hi ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory E:\Java\JavaEE\Demo\hi\src\test\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ hi ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to E:\Java\JavaEE\Demo\hi\target\test-classes
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ hi ---
[INFO] Surefire report directory: E:\Java\JavaEE\Demo\hi\target\surefire-reports
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running com.imooc.hi.hi.AppTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.054 sec
Results :
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ hi ---
[INFO] Building jar: E:\Java\JavaEE\Demo\hi\target\hi-0.0.1-SNAPSHOT.jar
[INFO]
[INFO] --- maven-source-plugin:2.4:jar-no-fork (default) @ hi ---
[INFO] Building jar: E:\Java\JavaEE\Demo\hi\target\hi-0.0.1-SNAPSHOT-sources.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 7.598 s
[INFO] Finished at: 2016-12-29T18:33:54+08:00
[INFO] Final Memory: 16M/129M
[INFO] ------------------------------------------------------------------------
我们看看项目hi下的变化:
配置插件
定义解释:插件目标
Maven插件高度易扩展,可以方便的进行自定义配置。当我们了解了maven插件之后,我们发现如果为每一个功
能编写一个独立的插件显然是不可取的,因为这些任务背后有很多可以复用的代码,因此,把这些功能聚集在一个插
件里,每一个功能我们就称之为一个插件目标。
举个例子:
maven-dependency-plugin有十多个目标,每个目标对应了一个功能
分析项目依赖:dependency:analyze
列出项目依赖树:dependency: tree
列出项目所有已解析的依赖:dependency:list
POM中插件全局配置
有些参数的值从项目的创建到项目发布都不会改变,或者说很少改变,对于这种情况,就可以在pom.xml中进行
全局配置。
例如:配置maven-compiler-plugin插件编译源代码的JDK版本为1.8:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.4</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
这样,不管绑定到compile阶段的maven-compiler-plugin: compile 还是绑定到test-compiler 阶段的maven-
compiler-plugin: testCompiler 任务,就都能够使用该配置,基于JavaSE1.8版本进行编译。
插件仓库
跟其他构件一样,插件也是根据坐标存储在Maven仓库中。超级POM中Maven配置的默认插件远程仓库如下:
<pluginRepositories>
<pluginRepository>
<id>central</id>
<name>Central Repository</name>
<url>http://repo.maven.apache.org/maven2</url>
<layout>default</layout>
<snapshots>
<enabled>false</enabled>
</snapshots>
<releases>
<updatePolicy>never</updatePolicy>
</releases>
</pluginRepository>
</pluginRepositories>
Maven生命周期和插件就说到这里。