maven生命周期与插件-阿里云开发者社区

开发者社区> 开发与运维> 正文

maven生命周期与插件

简介:
生命周期 
在有关Maven的日常使用中,命令行的输入往往就对应了生命周期,如mvn package就表示执行默认生命周期阶段package. 


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


Maven的生命周期是抽象的,这意味着生命周期本身不做任何实际的工作,在Maven的设计中,实际的任务(如编译源代码)都交由插件来完成。 


生命周期抽象了构建的各个步骤,定义了他们的次序,但没有提供具体实现,Maven通过插件机制,每个构建步骤都可以绑定一个或者 
多个插件行为,而且Maven为大多数构建步骤编写并绑定了默认插件。 


Maven定义的生命周期和插件机制一方面保证了所有Maven项目有一致的构建标准,另一方面又通过默认插件简化和稳定了实际项目的构建。 
此外,该机制还提供了足够的扩展空间,用户可以通过配置现有插件或者自行编写插件来自定义构建行为。 




三套生命周期:分别为clean、default、site 
每个生命周期包含一些阶段(phase),这些阶段是有顺序的,并且后面的阶段依赖于前面的阶段,用户和Maven最直接的交互方式就是调用这些 
生命周期阶段。 


较之于生命周期阶段的前后依赖关系,三套生命周期本身是相互独立的,用户可以仅仅调用clean生命周期的某个阶段,或者仅仅调用default 
生命周期的某个阶段,而不会对其他生命周期产生任何影响。 


clean生命周期:目的是清理项目,包含pre-clean,clean,post-clean 
default生命周期:目的是构建项目,定义了真正构建时所需要执行的所有步骤,它是所有生命周期中最核心的部分,包含如下阶段: 
validate 
initialize 
generate-sources 
process-sources 
generate-resources 
process-resources:处理项目主资源文件,一般来说是对src/main/resources目录的内容进行变量替换等工作后,复制到项目输出的主classpath目录中 
compile 
process-classes 
generate-test-sources 
process-test-sources 
generate-test-resources 
process-test-resources 
test-compile 
process-test-classes 
test:使用单元测试框架运行测试,测试代码不会被打包或部署 
prepare-package 
package:接受编译好的代码,打包成可发布的格式,如jar 
pre-integration-test 
integration-test 
post-integration-test 
verify 
install:将包安装到Maven本地仓库,供本地其他Maven项目使用 
deploy:将最终的包复制到远程仓库,供其他开发人员和Maven项目使用 


site生命周期:目的是建立和发布项目站点,Maven能够基于POM所包含的信息,自动生成一个友好的站点 
方便团队交流和发布项目信息,包含如下阶段 
pre-site 
site 
post-site 
site-deploy:将生成的项目站点发布到服务器上。 


命令执行与生命周期 
$mvn clean:该命令调用clean生命周期的clean阶段。实际执行的阶段为clean生命周期的pre-clean和clean 
$mvn test:该命令调用default生命周期的test阶段。实际执行的阶段为default生命周期的validate、initialize等, 
直到test的所有阶段 
$mvn clean deploy site-deploy:该命令调用clean生成周期的clean阶段、default生成周期的deploy阶段,以及site生命 
周期的site-deploy阶段。实际执行的阶段为clean生命周期的pre-clean,clean阶段,default生命周期的所有阶段, 
以及site生命周期的所有阶段。 


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


如dependency:analyze,dependency:tree,dependency:list,冒号后面是插件maven-dependency-plugin的目标, 
compiler:compile, surefire:test 

default生命周期的阶段与插件目标的绑定关系是由项目打包类型决定,打包类型是通过POM中的packaging元素定义的。 


除了内置绑定外,还可以自定义绑定,用户还能够自己选择将某个插件目标绑定到生命周期的某个阶段上。如创建项目的源代码jar包 
<plugin> 
<groupId>org.apache.maven.plugins</groupId> 
<artifactId>maven-source-plugin</artifactId> 
<version>2.2.1</version> 
<executions> 
<execution> 
<id>attach-sources</id> 
<phase>compile</phase> 
<goals> 
<goal>jar-no-fork</goal> 
</goals> 
</execution> 
</executions> 
</plugin> 


phase元素是可选的,因为有很多插件的目标在编写时已经定义了默认绑定阶段,可以使用maven-help-plugin查看插件详细信息,了解插件 
目标的默认绑定阶段。 
运行命令如下: 
$mvn help:describe -Dplugin=org.apache.maven.plugins:maven-source-plugin:2.2.1 
$mvn help:describe -Dplugin=org.apache.maven.plugins:maven-compiler-plugin:2.3.2 


查看maven-surefire-plugin插件test目标的详细介绍 
mvn surefire:help -Ddetail=true -Dgoal=test 




当插件目标被绑定到不同的生命周期阶段的时候,其执行顺序会由生命周期阶段的先后顺序决定 
如果多个目标被绑定到同一个阶段,这些插件声明的先后顺序决定了目标的执行顺序 


插件配置 
用户可以配置插件目标的参数,进一步调整插件目标所执行的任务,以满足项目的需求 


命令行插件配置: 
maven-surefire-plugin提供了一个maven.test.skip的参数,当其值为true的时候,就会跳过执行测试。 
mvn package -Dmaven.test.skip=true 
参数-D是Java自带的,其功能是通过命令设置一个Java系统属性,Maven简单地重用了该参数,在准备参数 
的时候检查系统属性,便实现了插件参数的配置 


POM中插件全局配置(为插件配置全局参数) 
并不是所有的插件参数都适合从命令行配置,有些参数的值从项目创建到项目发布都不会改变,或者说很少改变, 
对于这种情况,在POM文件中一次性配置就显然比重复在命令行输入要方便。 


用户可以在声明插件的时候,对此插件进行一个全局的配置,即所有该基于该插件目标的任务,都会使用这些配置。 
如通常会需要配置maven-compiler-plugin告诉它编译Java1.6版本的源文件,生成与JVM1.6兼容的字节码文件。 
<plugin> 
<groupId>org.apache.maven.plugins</groupId> 
<artifactId>maven-compiler-plugin</artifactId> 
<version>2.1</version> 
<configuration> 
<source>1.6</source> 
<target>1.6</target> 
</configuration> 
</plugin> 


POM中插件任务配置:为某个插件任务配置特定的参数 
如maven-antrun-plugin,它有一个目标run,可以用来在Maven中调用ant任务。 


获取插件信息 
因为大部分插件完善的文档,因此使用正确的插件并进行正确的配置,并不是一件容易的事 
基本上所有主要的Maven插件都来自Apache和Codehaus 
除了Apache上的官方插件之外,托管于Codehaus上的Mojo项目也提供了大量的Maven插件 
http://maven.apache.org/plugins/index.html 
http://repo.maven.apache.org/maven2/org/apache/maven/plugins/ 


http://mojo.codehaus.org/plugins.html 
http://repository.codehaus.org/org/codehaus/mojo/  (目前下面无内容) 
注意:这些插件的文档和可靠性相对较差,在使用时,如果遇到问题,往往只能自己看源代码。 


googlecode插件列表: 
http://code.google.com/hosting/search?q=maven+plugin+label%3Amaven&projectsearch=Search+Project 


不加版本信息,是让Maven自动获取最新版本来进行表述: 
$mvn help:describe -Dplugin=org.apache.maven.plugins:maven-source-plugin:2.2.1 
$mvn help:describe -Dplugin=org.apache.maven.plugins:maven-compiler-plugin:2.3.2 


查看maven-surefire-plugin插件test目标的详细介绍 
mvn help:describe -Dplugin=compiler 
mvn help:describe -Dplugin=compiler -Ddetail=true 
mvn help:describe -Dplugin=compiler -Dgoal=compile 
mvn surefire:help -Ddetail=true -Dgoal=test 


从命令行调用插件 
usage: mvn [options] [<goal(s)>] [<phase(s)>] 
options 表示可用的选项 
除了选项之外,mvn命令后面可以添加一个或者多个goal和phase,它们分别是指插件目标和生命周期阶段 


可以通过mvn命令激活生命周期阶段,从而执行那些绑定在生命周期阶段上的插件目标, 
还支持直接从命令行调用插件目标,因为有些任务不适合绑定在生命周期上, 
如maven-help-plugin:describe :不需要在构建项目的时候去描述插件信息 
 maven-dependency-plugin:tree:不需要在构建项目的时候去显示依赖树 


因为这些插件目标应该通过如下方式使用 
mvn help:describe -Dplugin=compiler 
mvn dependency:tree 


mvn org.apache.maven.plugins:maven-help-plugin:2.1.1:describe -Dplugin=compiler 


这种方式是通过插件前缀实现的(否则要写全groupId、artifactId、version),有了插件前缀,Maven就能找到对应的artifactId 


插件解析机制 
为了方便用户使用和配置插件,Maven不需要用户提供完整的插件坐标信息,就可以解析得到正确的插件。 


插件仓库 
插件同样基本坐标存储在Maven仓库中。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> 


 1:插件从来不从远程仓库检查更新 
 2:插件的默认groupId为org.apache.maven.plugins,如果是Maven的官方插件,则可以省略groupId配置 
  
 解析插件版本: 
 1:Maven在超级POM中为所有核心插件设定了版本,超级POM是所有Maven项目的父POM,所有项目都继承这个 
超级POM的配置 
 2:如果使用某个插件没有设定版本,而此插件又不属于核心插件的范畴,Maven就会检查最新的RELEASE版本 
 3:解析插件前缀:插件前缀与groupId:artifactId是一一对应的,这种匹配关系存储在仓库元数据中。 
这里的仓库元数据为groupId/maven-metadata.xml 
http://repo1.maven.org/maven2/org/apache/maven/plugins/maven-metadata.xml 

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:
开发与运维
使用钉钉扫一扫加入圈子
+ 订阅

集结各类场景实战经验,助你开发运维畅行无忧

其他文章