五. 生命周期和插件

    除了坐标、依赖以及仓库外,Maven另外两个核心概念是生命周期和插件。声明周期和插件两者协同工作

 

1.什么是生命周期

 

    Maven的生命周期就是为了对所有的构建过程进行抽象和统一。这个生命周期包含了项目的清理、初始化、编译、测试、打包、集成测试、验证、部署和站点生成等所有的构建步骤。

    Maven的生命周期是抽象的,生命周期本身不做任何实际工作,在Maven的设计中,实际的任务(如编译源代码)都交由插件完成。类似于设计模式中的模板方法(Template Method)。

    每个构建步骤都可以绑定一个或者多个插件行为,而且Maven为大多数构建步骤编写并绑定了默认插件。

例如:

    针对编译的插件maven-compiler-plugin;针对测试的插件maven-surefire-plugin。

 

2.生命周期详解

 

(1)三套生命周期

clean:清理项目

default:构建项目

site:建立站点

    每个生命周期包含一些阶段(phase),这些阶段是顺序的,并且后面的阶段依赖与前面的阶段。即调用后面的阶段,之前的阶段会被顺序执行。

三套生命周期本身是项目独立的,用户可以仅仅调用clean生命周期的某个阶段,或者仅仅调用default生命周期的某个阶段,而不会对其他生命周期产生影响。

 

(2)clean生命周期

    clean生命周期的目的是清理项目

1) pre-clean 执行一些清理前需要完成的工作;

2) clean 清理上一次构建生成的文件;

3) post-clean 执行一些清理后需要完成的工作。

 

(3)default生命周期

    default生命周期定义了真正构建时所需要执行的的所有步骤,它是所有生命周期中最核心的部分

1) validate

2) initialize

3) generate-sources

4) process-sources 处理项目主资源文件。一般来说是对src/main/resources目录的内容进行变量替换等工作后,复制到项目输出主classpath中;

5) generate-resources

6) process-resources

7) compile 编译项目的主代码。一般来说是编译src/main/java目录下的Java文件至项目输出的主classpath目录中

8) process-class

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-class

15) test 使用单元测试框架运行测试,测试代码不会被打包部署

16) prepare-package

17) package 接受编译好的代码,打包成可发布的格式,如JAR

18) pre-integration-test

19) integration-test

20) post-integration-test

21) verify

22) install 将包安装到Maven本地仓库,供本地其他Maven项目使用

23) deploy 将最终的包复制到远程仓库,供其他开发人员和Maven项目使用

 

(4)site生命周期

    site生命周期的目的是建立和发布项目站点,Maven能够基于POM所包含的的信息,自动生成一个友好的站点,方便团队交流和发布项目信息

1) pre-site:执行一些在生成项目站点之前需要完成的工作;

2) site:生成项目站点文档

3) post-site:执行一些在生成项目站点之后需要完成的工作;

4) site-deploy:将生成的项目站点发布到服务器上

 

(5)执行生命周期

    从命令行执行Maven任务的主要方式就是调用Maven的生命周期阶段,需要注意各个生命周期是相互独立的,而一个生命周期的阶段是有前后依赖关系的。

例:

    mvn clean:调用clean生命周期的clean阶段,实际执行为clean生命周期的pre-clean和clean阶段;

    mvn test:调用default生命周期的test阶段,实际执行为default生命周期的validate、initialize到test阶段;

    mvn clean install:该命令调用clean生命周期的clean阶段和default声明周期的install阶段。实际执行的阶段为clean生命周期的pre-clean和clean阶段,以及default生命周期的validate、initialize到install阶段

    mvn clean deploy site-deploy:该命令调用clean生命周期的clean阶段、default声明周期的deploy阶段,以及site生命周期的site-deploy阶段。

    由于Maven中主要的生命周期阶段并不多,而常用的Maven命令实际就是基于这些阶段简单组合而成的。

 

3.插件目标(Plugin Goal)

 

    对于插件本身为了复用代码,往往能够完成多个任务

    maven-dependency-plugin有十多个目标,分析项目依赖,帮助找出无用依赖:dependency:analyze;列出项目所有依赖:dependency:tree和dependency:list 。

    冒号前面是插件前缀,冒号后面是插件目标类似compiler:compiler(maven-compiler-plugin的compile目标)和surefire:test(maven-surefire-plugin的test目标)。

 

4.插件绑定

 

    Maven的生命周期与插件互相绑定,用以完成实际的构建任务。具体而言,是生命周期的阶段与插件的目标互相绑定,已完成某个具体的构建任务。

(1)内置绑定

    Maven在核心为一些主要的生命周期阶段绑定了很多插件目标,当用户通过命令调用生命周期阶段的时候,对应的插件目标就会执行相应的任务。

    clean生命周期中clean与maven-clean-plugin:clean绑定

    site生命周期中site和maven-site-plugin:site绑定,site-deploy与maven-site-plugin:deploy互相绑定

default生命周期见下表

生命周期阶段 插件目标 执行任务
process-resources maven-resources-plugin:resources 复制主资源文件至主输出目录
compile maven-compiler-plugin:compile 编译主代码至主输出目录
process-test-resources maven-resources-plugin:testResources 复制测试资源文件至测试输出目录
test-compile maven-compiler-plugin:testCompile 编译测试代码至测试输出目录
test maven-surefire-plugin:test 执行测试用例
package maven-jar-plugin:jar 创建项目jar包
install maven-install-plugin:install 将项目输出构件安装到本地仓库
deploy maven-deploy-plugin:deploy 将项目输出构件部署到远程仓库

 

    注意:表中只列出了拥有插件绑定关系的阶段,default生命周期还有很多其他阶段,默认他们没有绑定任何插件,因此没有任何实际行为

    除了默认的jar之外,常见的打包类型还有war(maven-war-plugin)等

 

<!-- 使用UTF-8编码处理资源文件 -->
<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-resources-plugin</artifactId>
	<version>2.6</version>
	<configuration>
		<encoding>UTF-8</encoding>
	</configuration>
</plugin>
<!-- 打war包 -->
<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-war-plugin</artifactId>
	<version>2.3</version>
	<configuration>
		<outputDirectory>${basedir}/../war/${env}</outputDirectory>
	</configuration>
	<executions>
		<execution>
			<id>attach-war</id>
			<phase>package</phase>
			<goals>
				<goal>war</goal>
			</goals>
		</execution>
	</executions>
</plugin>

 

(2)自定义绑定

    用户能够选择某个插件目标绑定到生命周期的某个阶段上

例子:通过maven-source-plugin:jar-no-fork绑定到default生命周期的verify阶段上创建项目的源码jar包

 

	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-source-plugin</artifactId>
				<version>2.2.1</version>
				<executions>
					<execution>
						<id>attach-sources</id>
						<phase>verify</phase>
						<goals>
							<goal>jar-no-fork</goal>
						</goals>
					</execution>
				</executions>
			</plugin>
		<plugins>
	<build>
    在POM的build元素下的plugins子元素中声明插件的使用,基本的插件坐标声明为org.apache.maven.plugins:maven-source-plugin:2.2.1

 

    除了基本插件坐标声明外,还要有插件执行配置,executions下面每个execution子元素可以用来配置执行一个任务。

    这里配置了id为attach-sources的任务,通过phase配置,将其绑定到verify生命周期阶段上,在通过goals-goal配置指定要执行的插件目标。

执行

 

mvn clean verify
在$M2_HOME/target/目录下发现helloWorld-1.0-SNAPSHOT-sources.jar,另外若不定义phase标签,则该目标会被绑定到package阶段。

 

 

5.插件配置

 

    完成了插件和生命周期的绑定后,用户还可以配置插件目标的参数,进一步调整插件目标所执行的任务,以满足项目的需求。几乎所有的Maven插件都有一些可配置参数。

 

(1)命令行插件配置

    在Maven中使用-D参数,并伴随一个 参数键 = 参数值 的形式

例如,maven-surefire-plugin提供了一个maven.test.skip的参数,当其值为true的时候,就会跳过执行测试。

 

mvn clean verify -Dmaven.test.skip=true
     参数-D是Java自带的,其功能是通过命令行设置一个Java系统属性,Maven简单的重用了该参数,在准备插件的时候检查系统属性,便实现了插件参数的配置

 

 

(2)POM中插件全局配置

    有些参数的值从项目创建到发布都不会改变,对于这种情况,在POM文件中一次性配置就显得比重复在命令行输入要方便

    用户可以在声明插件的时候,对此插件进行一个全局配置。也就是说所有基于该插件目标的任务,都会使用这些配置。

    例如:配置maven-compiler-plugin,用于编译Java1.6版本的源文件,生成与JVM1.6兼容的字节码文件。

 maven的核心插件之一---complier插件默认只支持编译Java 1.4,因此需要加上支持高版本jre的配置

<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-compiler-plugin</artifactId>
	<version>3.1</version>
	<configuration>
		<source>1.6</source>
		<target>1.6</target>
                <encoding>UTF-8</encoding>
                <showWarnings>true</showWarnings>
	</configuration>
</plugin>
     这样,不管绑定到compile阶段的maven-compiler-plugin:compile任务,还是绑定到test-compiler阶段的maven-compiler-plugin:testCompile任务都能使用该配置,基于Java1.6版本进行编译。

 

 

(3)POM中插件任务配置

    可以为某个插件任务配置特点的参数。

    例如:maven-antrun-plugin为例,他有一个目标run,可以用来在Maven中调用Ant任务。用户将maven-antrun-plugin:run绑定到多个生命周期阶段上,再加以不同的配置,就可以让Maven在不同的生命周期阶段执行不同的任务

 

<project>
... ...
	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-antrun-plugin</artifactId>
				<version>1.7</version>
				<executions>
					<execution>
						<id>ant-validate</id>
						<phase>validate</phase>
						<goals>
							<goal>run</goal>
						</goals>
						<inherited>false</inherited>
						<configuration>
							<tasks>
								<echo>I'm bound to validate phase.</echo>
							</tasks>
						</configuration>
					</execution>
					<execution>
						<id>ant-verify</id>
						<phase>verify</phase>
						<goals>
							<goal>run</goal>
						</goals>
						<configuration>
							<tasks>
								<echo>I'm bound to verify phase.</echo>
							</tasks>
						</configuration>
					</execution>
				</executions>
			</plugin>
		</plugins>
	</build>
</project>
    首先 maven-antrun-plugin:run 与 validate阶段绑定,从而构成一个id为ant-validate的任务,插件全局配置中的configuration元素位于plugin元素下面,而这里的configuration元素位于execution元素下,表示这是特定任务的配置,而非插件整体的配置。这个ant-validate配置了一个echo Ant的任务,向命令行输出一段文字,表示该任务是绑定到validate阶段的。

 

    第二个任务id为ant-verify,绑定到了verify阶段同样输出一段文字,表示该任务是绑定到verify阶段的。

 

6.获取插件信息

 

    需要了解去哪里寻找合适的插件,以及该插件的配置点

 

(1)在线插件信息

基本上所有主要的Maven插件都来自Apache和Codehaus

Apache详细列表在 : http://maven.apache.org/plugins/index.html

下载地址在:http://repo.maven.apache.org/maven2/org/apache/maven/plugins/

(2)使用maven-help-plugin描述插件

借助maven-help-plugin来获取插件的详细描述信息

mvn help:describe -Dplugin=org.apache.maven.plugins:maven-compiler-plugin:3.1
 还可以省去版本信息,让Maven自动获取最新版本进行描述
mvn help:describe -Dplugin=org.apache.maven.plugins:maven-compiler-plugin
 还可以进一步,可以使用插件目标前缀替换坐标
mvn help:describe -Dplugin=compiler
 如果仅仅描述某个插件目标的信息,可以加上goal参数
mvn help:describe -Dplugin=compiler -Dgoal=compile
 如果想让maven-help-plugin输出更详细的信息,可以加上detail参数
mvn help:describe -Dplugin=compiler -Ddetail
 help:effective-pom 显示当前构建的实际 POM ,包含活动的Profile。  
mvn help:effective-pom

 

 

7.从命令行调用插件

 

通过调用命令帮助

 

mvn -h
 查看mvn的基本用法usage: mvn [options] [<goal(s)>] [<phase(s)>]

 

options:可用选项,20多个;

goal:插件目标,可以多个;

phase:生命周期阶段,可多个

有些任务不适合绑定到生命周期上,如maven-help-plugin:describe,我们不需要在构建项目的时候去描述插件信息,又如maven-dependency-plugin:tree,也不需要构建项目的时候显示依赖,因此使用方式如下:

 

mvn help:describe -Dplugin=compiler
mvn dependency:tree
 
其中help和dependency是目标前缀,Maven允许通过目标前缀找到artifcatId,可以通过下面命令查看

 

mvn help:describe -Dplugin=help

 

8.插件解析机制

 

(1)插件仓库

    插件构建坐标存储在Maven仓库中

$M2_HOME/lib/maven-model-builder-3.0.4.jar,然后访问maven-model-builder-3.0.4.jar\org\apache\maven\model\pom-4.0.0.xml,可以看到如下信息:

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

    除了pluginRepository标签与repository标签不一致外,其它完全一样

    可以看到关闭了对snapshot版本的支持;updatePolicy:never从不检测更新。

 

(2)插件的默认groupId

    在POM中配置插件的时候,如果该插件是Maven的官方插件(即groupId为org.apache.maven.plugins),就可以省略groupId配置。

    不推荐使用Maven这一机制。

 

(3)解析插件版本

    第一种情况:核心插件,Maven在超级POM中为所有核心插件设定了版本,包括maven-clean-plugin、maven-compiler-plugin、maven-surefire-plugin等

    第二种情况:非核心插件,Maven会在中央仓库中读取元数据,并计算release版本(最新非快照版本)和latest版本(最新版本),不推荐这样做。

 

(4)解析插件前缀

    插件前缀如groupId:atrifactId是一一对应的,这种匹配关系存储在仓库的元数据中。仓库元数据为groupId/maven-metadata.xml

你可能感兴趣的:(生命周期)