除了坐标、依赖以及仓库外,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/