掌握Maven_2
来源:互联网 发布:淘宝企业店铺开店装修 编辑:程序博客网 时间:2024/06/09 16:29
五、生命周期和插件
Maven的生命周期包含了项目的清理、初始化、编译、测试、打包、集成测试、验证、部署和站点生成等,几乎所有的构建步骤。
Maven的生命周期是抽象的,定义了各个构建步骤的次序,但没有提供具体实现。具体的构建步骤由插件实现。通过插件机制,每个构建步骤可以绑定一个或者多个插件行为。
1、生命周期
(1)、三套生命周期
Maven拥有三套相互独立的生命周期:clean、default、site。
每个生命周期包含一些阶段(phase),这些阶段是有顺序的,后面的阶段依赖于前面的阶段。
【】clean生命周期
目的是清理项目,包含三个阶段:
** pre-clean : 执行一些清理前需要完成的工作
** clean:清理上一次构建生成的文件
** post-clean:执行一些清理后需要完成的工作
【】default生命周期
目的:定义真正构建时所需的执行步骤,其包含的阶段如下:
** validate
** initialize
** generate-sources
** process-sources : 处理项目主资源 文件,一般是对src/main/resources目录的内容进行变量替换等工作后,复制到项目输出的主classpath目录中。
** generate-resources
** process-resources
** compile :编译项目的主源码,一般是编译src/main/java目录下的Java文件至项目输出的主classpath目录中。
** process-classes
** generate-test-sources
** process-test-sources : 处理项目测试资源文件。一般来说,是对src/test/resources目录的内容进行变量替换等工作后,复制到项目输出的测试classpath目录中。
** generate-test-resources:
** prosess-test-resource:
** test-compile:编译项目的测试代码,一般来说,是编译src/test/java目录下的Java文件至项目输出的测试classpath目录中。
** process-test-classes:
** test:使用单元测试框架运行测试,测试代码不会被打包或部署
** prepare-package
** package:接受编译好的代码,打包成可发布的格式,如JAR。
** pre-integration-test
** integration-test
** post-integration-test
** verify
** install : 将包安装到Maven本地仓库,供本地其他Maven项目使用
** deploy:将最终的包复制到远程仓库,供其他开发人员和Maven项目使用。
【】site生命周期
site生命周期的目的是建立和发布项目站点,Maven能够基于POM所包含的信息,自动生成一个友好的站点,方便团队交流和发布项目信息。该生命周期包含如下阶段:
** pre-site:执行一些在生成项目站点之前需要完成的工作。
** site:生成项目站点文档
** post-site:执行一些在生成项目站点之后需要完成的工作。
** site-deploy:将生成的项目站点发布到服务器上。
2、插件目标(Plugin Goal)
Maven的核心仅仅定义了抽象的生命周期,具体的任务是交由插件完成的,插件以独立的构件形式存在。对于插件来讲,每一插件都能完成多个功能,每个功能就是一个插件目标。
关于插件目标的通用写法是:冒号前面是插件前缀,冒号后面是该插件的目标。例如:dependency:analyze、dependency:tree和dependency:list
3、插件绑定
Maven生命周期的阶段与插件的目标相互绑定,以完成某个具体的构建任务。例如,对于项目编译这一任务,它对应了dafault生命周期的compile这一阶段,而maven-compiler-plugin这一插件的compile目标能够完成该任务,因此,将它们绑定,就能实现项目编译的目的。
(1)、内置绑定
为了能让用户几乎不用任何配置就能构建Maven项目,Maven在核心为一些主要的生命周期阶段绑定了许多插件的目标,当用户通过命令行调用生命周期阶段的时候,对应的插件目标就会执行相应的任务。
clean生命周期中的clean阶段与maven-clean-plugin:clean绑定;
site生命周期的site阶段与maven-site-plugin:site绑定;
site生命周期的site-deploy阶段与maven-site-plugin:deploy绑定;
由于项目的打包类型会影响构建的具体过程,因此default生命周期的阶段与插件目标的绑定关系由项目打包类型所决定。
基于jar打包类型的项目,其dafault生命周期的内置插件绑定关系及具体任务如下表:
注意:default生命周期还要很多其他阶段,默认它们没有绑定任何插件,因此也没有任何实际行为。
打包类型除jar之外,常见的还有war、pom、maven-plugin、ear等。
(2)、自定义绑定
除了内置绑定以外,用户还能够自动选择将某个插件目标绑定到生命周期的某个阶段。
具体做法:
在项目的POM文件的build元素下的plugins子元素中声明插件的使用,除了基本的插件坐标声明外,还有配置插件的执行配置,executions下每个execution子元素可用来配置执行一个任务。executions子元素下的id指定任务名,phrase配置绑定的生命周期阶段,goals配置指定要执行的插件目标。
注意:对于自定义绑定的插件,用户不应该使用快照版本,这样可以避免由于插件版本变化造成的构建不稳定性。
当多个插件目标绑定到同一个阶段的时候,这些插件声明的先后顺序决定了目标的执行顺序。
4、插件配置
几乎所有的Maven插件的目标都有一些可配置的参数,用户可通过命令行和POM配置等方式来配置这些参数。
(1)、命令行插件配置
在Maven命令中使用-D参数,并伴随一个参数键=参数值的形式,来配置插件目标的参数。例如跳过测试执行的参数设置:
mvn install -D maven.test.skip = true
对于一些经常变化的开关类配置参数,可以通过命令行配置。
(2)、POM中插件全局配置
在POM文件,<build>元素下的<plugins>元素下的<plugin>元素中直接配置子元素<configuration>,那么所有基于该插件目标的任务,都会使用这些配置。
对于一些项目整个过程中都不变的一些配置参数,可以使用POM插件全局配置。
(3)、POM中插件任务配置
用户还可以为某个插件任务配置特定的参数。在execution元素下配置子元素<configuration>,就是对特定任务的配置。
例如,一个插件目标可以绑定到多个生命周期阶段上,加上不同的配置,就可以让Maven在不同的生命周期阶段执行不同的任务,如:
<build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-antrun-plugin</artifactId><version>1.3</version><executions><execution><id>ant-validate</id><phase>validate</phase><goals><goal>run</goal></goals><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>
5、获取插件信息
(1)、在线插件信息
基本上所有主要的Maven插件都来自Apache和Codehaus。详细的列表可以访问地址:http://maven.apache.org/plugins/index.html
(2)、使用maven-help-plugin描述插件
例如,获取maven-compiler-plugin 2.1版本的信息:
mvn help: describe -D plugin = org.apache.maven.plugins : maven-compiler-plugin:2.1
注:这里的参数plugin, 需要输入插件的groupId、artifactId、version
6、从命令行调用插件
mvn命令的作用是激活生命周期阶段,从而执行那些绑定在生命周期阶段上的目标插件。
mvn命令的格式是:mvn [options] [<goal(s)>] [<phase(s)>]
options表示可用的选项,goal表示插件目标,phase表示生命周期阶段。
此外,对于有些不适合绑定在生命周期上的插件目标,例如mave-help-plugin:describe,Maven还支持直接从命令行调用插件目标。调用方式如下:
mvn help:describe -D plugin = compiler
mvn dependency:tree
与如下命令作用一样:
mvn org.apache.maven.plugins:maven-help-pluginL2.1:describe -D plugin = compiler
mvn org.apache.maven.plugins:maven-dependency-plugin:2.1:tree
这里需要注意的是目标前缀(Goal Prefix)的概念,其作用是方便在命令行直接运行插件。help是maven-help-plugin的目标前缀,dependency是maven-dependency-plugin的前缀。
7、插件解析机制
(1)、插件仓库
Maven是会区别对待依赖的远程仓库和插件的远程仓库的。在POM或settings.xml文件中,repositories及其repository子元素对应的是依赖的远程仓库,pluginRepositories、pluginRepository子元素配置对应的插件远程仓库。
(2)插件的默认groupId
在配置插件时,如果是Maven官方的插件,就可以省略groupId配置,因为Maven在解析这样的插件时,会自动用默认groupId org.apache.maven.plugins补齐。
(3)解析插件版本
为简化插件配置和使用,在用户没有提供插件版本的情况下,Maven会自动解析插件版本。Maven在超级POM中为所有核心插件设定了版本,如果不是核心插件,其解析原理与仓库解析部分描述的一样,maven会归并本地仓库和所有远程仓库在该路径下的仓库元数据,就能计算出latest、release值。
注意:尽管maven可以解析插件版本,但推荐使用显式的版本设定,避免版本变化带来的项目构建失败。
(4)解析插件前缀(目标前缀)
maven从插件前缀解析得到插件坐标的原理如下:
首先,插件前缀与groupId:artifactId是一一对应的,这种匹配关系存储在仓库元数据中(注意是:groupId/maven-metadata.xml中);其次,groupId是默认或配置的,默认的两个是org.apache.maven.plugins、org.codehaus.mojo,配置的是指可以在settings.xml中配置让Maven检查其他的groupId,配置格式如下:
<settings><pluginGroups><pluginGroup>com.your.plugins</pluginGroup></pluginGroups></settings>然后,就可以根据解析插件版本的方法,解析出版本。如果所有元数据中都不包含该插件前缀,则报错。
示例:dependency:tree
maven首先基于默认的groupId归并所有插件仓库的元数据org.apache/maven/plugins/maven-metadta.xml;其次检查归并后的元数据,找到对应的artifactId为maven-dependency-plugin;然后结合当前元数据的groupId org.apache.maven.plugins,使用版本解析方法解析得到version,这样就得到完整的插件坐标。
六、聚合和继承
1、聚合
一般的项目都包含多个模块,为了方便一次构建项目下的所有模块,而不是一个一个模块地来构建项目。Maven提供了聚合特性。
聚合模块是为了多模块项目的聚合功能而存在的,其仅有一个pom.xml文件,它仅仅是帮助聚合其他模块构建的工具,本身并没有实质内容。
聚合模块的pom.xml文件中的packaging值必须为pom,否则无法构建;
聚合模块的最核心配置时modules,可以声明任意数量的module元素,每个module的值都是一个当前POM的相对目录,代表一个模块;
聚合模块可以与其他模块是父子目录关系,也可以是平行目录关系,一般为了方便用户构建项目,通常将聚合模块放在项目目录的最顶层,其他模块则作为聚合模块的子目录存在。
2、继承
对于多模块项目来讲,不仅有聚合POM, 还有各个模块的POM, 通常这些POM都有许多相同的配置,重复往往就意味着更多的劳动和更多的潜在问题,为了避免POM配置的重复,Maven提供了继承机制。
所谓,POM的继承,就是创建POM的父子结构,然后父POM中声明的配置可供子POM继承,以实现“一处声明,多处使用”的目的。
父模块的POM,其打包方式(packaging)必须为pom。而且由于父模块只是为了帮助消除配置的重复而存在,因此它除了POM之外不包含任何其他文件。
例如,有如下父模块POM:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.juvenxu.mvnbook.account</groupId><artifactId>account-parent</artifactId><version>1.0.0-SNAPSHOT</version><packaging>pom</packaging><name>Account Parent</name></project>子POM如果要继承该POM的内容,需要以下的元素声明:
<parent><groupId>com.juvenxu.mvnbook.account</groupId><artifactId>account-parent</artifactId><version>1.0.0-SNAPSHOT</version><relativePath>../account-parent/pom.xml</relativePath></parent>其中,parent元素下的子元素groupId、artifactId和version指定了父模块的坐标,这三个坐标是必须的。元素relativePath表示父模块POM的相对路径。
注:relativePath的默认值是../pom.xml,也就是说,Maven默认父POM在上一层目录下。
实现上述步骤后,子POM的配置就可以简化了,例如:坐标声明,可以省略groupId、version,
在子POM中坐标声明需要指定artifact、name,而对于groupId、version则可以省略,因为该子模块隐式地从父模块继承了这两个元素。如果用户需要子模块是不同的groupId或version,直接在POM中显示声明groupId、version就可以了,这样可以覆盖掉父类的声明。
注:一般常常将聚合模块和父模块合并为一个(即将聚合POM文件与继承中的父POM文件合并),这样既简化了配置,也方便维护。
(1)、可继承的POM元素
【】groupId : 项目组ID
【】version:项目版本
【】description:项目的描述信息
【】organization:项目的组织信息
【】inceptionYear:项目的创始年份
【】url:项目的URL地址
【】developers:项目的开发者信息
【】contributors:项目的贡献者信息
【】distributionManagement:项目的部署配置
【】issueManagement:项目的缺陷跟踪系统信息
【】ciManagement:项目的持续集成系统信息
【】scm:项目的版本控制系统信息
【】mailingLists:项目的邮件列表信息
【】propeerties:自定义的Maven属性
【】dependencies:项目的依赖配置
【】dependencyManagement:项目的依赖管理配置
【】repositories:项目的仓库配置
【】build:包括项目的源码目录配置、输出目录配置、插件配置、插件管理配置等
【】reporting:包括项目的报告输出目录配置、报告插件配置等。
(2)、依赖管理
如上所列,dependencies元素可以被继承,但是一般不直接将子模块的共同依赖放置到父模块中,因为当增加新的子模块时,新的子模块就可能会从父模块中继承不必要的依赖。
为了解决上述问题,为了更加灵活地消除依赖重复配置,Maven提供的dependencyManagement元素既能让子模块继承到父模块的依赖配置,又能保证子模块依赖使用的灵活性。
在父模块的dependencyManagement声明的依赖既不会给父模块引入依赖,也不会给它的子模块引入依赖,但是该配置会被继承,当父模块POM中,声明的dependencyManagement提供了依赖的完整坐标,子模块的POM中,就可以省略version,仅仅配置依赖的groupId、artifact。
虽然,这种依赖管理机制不能减少太多的POM配置,不过还是建议采用这种方法,因为在父POM中使用dependencyManagement声明依赖能够统一项目范围中依赖的版本,降低依赖冲突的几率。
如果子模块不声明依赖的使用,即使该依赖已经在父POM的dependencyManagement中声明了,也不会产生任何实际的效果。
(3)、复制配置
名为import的依赖范围,仅在dependencyManagement元素下才有效果,使用该范围的依赖通常指向一个POM,作用是将目标POM中的dependencyManagement配置导入并合并到当前POM的dependencyManagement元素中。这样就达到了复制配置的目的。
(4)、插件管理
与依赖管理dependencyManagement类似,Maven提供了插件管理pluginManagement。在该元素中配置的插件不会造成实际的插件调用行为,当POM中配置了真正的plugin元素,并且其groupId、artifactId与pluginManagement中配置的插件匹配时,pluginManagement的配置才会影响实际的插件行为。
3、聚合与继承的关系
聚合主要是为了方便快速构建项目,继承主要是为了消除重复配置。
注:现实项目中,常常一个POM既是聚合POM,又是父POM。
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.juvenxu.mvnbook</groupId><artifactId>my-project</artifactId><version>1.0.0-SNAPSHOT</version><packaging>pom</packaging><name>Account Parent</name><build><sourceDirectory>src/java</sourceDirectory></build></project>上述示例中,源码目录变成了src/java而不是默认的src/main/java。
6、反应堆(Reator)
- 掌握Maven_2
- maven_2
- 掌握
- 掌握 C#
- 系统掌握。
- 掌握 Ajax
- 掌握 Ajax
- 掌握 Ajax
- 掌握Ajax
- 掌握Ajax
- 掌握 Ajax
- 掌握 Ajax
- 掌握sizeof
- 掌握AJAX
- 掌握 Ajax
- 掌握sizeof
- 掌握AJAX
- 掌握udev
- CAS原理深度分析
- 如何使用超级表格高效管理兼职人员信息?
- 理解JS的浅拷贝和深拷贝
- Java对象设计成OOP-Klass
- 两句代码搞定安卓拍照,选取照片,截取照片的所有操作
- 掌握Maven_2
- C#复制、剪切、创建文件
- Python使用Phantomjs截屏网页
- Java虚拟机设置Xms Xmx PermSize MaxPermSize
- 循环例题
- 静态方法和实力方法的定义与调用
- ItelliJ IDEA快捷键-常用
- 2016年度最受欢迎中国开源软件
- java如何用for循环编写十进制转换二进制的算法(精)。