天天看点

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兼容的字节码文件。 

<artifactid>maven-compiler-plugin</artifactid> 

<version>2.1</version> 

<configuration> 

<source>1.6</source> 

<target>1.6</target> 

</configuration> 

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

mvn help:describe -dplugin=compiler -ddetail=true 

mvn help:describe -dplugin=compiler -dgoal=compile 

从命令行调用插件 

usage: mvn [options] [<goal(s)>] [<phase(s)>] 

options 表示可用的选项 

除了选项之外,mvn命令后面可以添加一个或者多个goal和phase,它们分别是指插件目标和生命周期阶段 

可以通过mvn命令激活生命周期阶段,从而执行那些绑定在生命周期阶段上的插件目标, 

还支持直接从命令行调用插件目标,因为有些任务不适合绑定在生命周期上, 

如maven-help-plugin:describe :不需要在构建项目的时候去描述插件信息 

 maven-dependency-plugin:tree:不需要在构建项目的时候去显示依赖树 

因为这些插件目标应该通过如下方式使用 

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