Maven实战(七,八)——经常使用Maven插件介绍

时间:2023-04-08 23:13:26

我们都知道Maven本质上是一个插件框架,它的核心并不运行不论什么详细的构建任务,全部这些任务都交给插件来完毕,比如编译源代码是由maven-compiler-plugin完毕的。进一步说,每一个任务相应了一个插件目标(goal),每一个插件会有一个或者多个目标,比如maven-compiler-plugin的compile目标用来编译位于src/main/java/文件夹下的主源代码。testCompile目标用来编译位于src/test/java/文件夹下的測试源代码。

用户能够通过两种方式调用Maven插件目标。第一种方式是将插件目标与生命周期阶段(lifecycle phase)绑定。这样用户在命令行仅仅是输入生命周期阶段而已。比如Maven默认将maven-compiler-plugin的compile目标与compile生命周期阶段绑定。因此命令mvn compile实际上是先定位到compile这一生命周期阶段,然后再依据绑定关系调用maven-compiler-plugin的compile目标。另外一种方式是直接在命令行指定要运行的插件目标,比如mvn
archetype:generate 就表示调用maven-archetype-plugin的generate目标,这样的带冒号的调用方式与生命周期无关。

认识上述Maven插件的基本概念能帮助你理解Maven的工作机制。只是要想更高效率地使用Maven。了解一些经常使用的插件还是非常有必要的。这能够帮助你避免一不小心又一次发明*。多年来Maven社区积累了大量的经验。并随之形成了一个成熟的插件生态圈。Maven官方有两个插件列表,第一个列表的GroupId为org.apache.maven.plugins,这里的插件最为成熟。详细地址为:http://maven.apache.org/plugins/index.html

第二个列表的GroupId为org.codehaus.mojo,这里的插件没有那么核心。但也有不少十分实用,其地址为:http://mojo.codehaus.org/plugins.html

接下来笔者依据自己的经验介绍一些最经常使用的Maven插件,在不同的环境下它们各自都有其出色的表现,熟练地使用它们能让你的日常构建工作事半功倍。

maven-antrun-plugin

http://maven.apache.org/plugins/maven-antrun-plugin/

maven-antrun-plugin能让用户在Maven项目中执行Ant任务。用户能够直接在该插件的配置以Ant的方式编写Target。然后交给该插件的run目标去执行。在一些由Ant往Maven迁移的项目中,该插件尤事实上用。此外当你发现须要编写一些自己定义程度非常高的任务,同一时候又认为Maven不够灵活时。也能够以Ant的方式实现之。

maven-antrun-plugin的run目标通常与生命周期绑定执行。

maven-archetype-plugin

http://maven.apache.org/archetype/maven-archetype-plugin/

Archtype指项目的骨架,Maven刚開始学习的人最開始运行的Maven命令可能就是mvn archetype:generate,这实际上就是让maven-archetype-plugin生成一个非常easy的项目骨架,帮助开发人员高速上手。可能也有人看到一些文档写了mvn archetype:create。但实际上create目标已经被弃用了,取而代之的是generate目标。该目标使用交互式的方式提示用户输入必要的信息以创建项目,体验更好。maven-archetype-plugin另一些其它目标帮助用户自定义项目原型。比如你由一个产品须要交付给非常多客户进行二次开发,你就能够为他们提供一个Archtype,帮助他们高速上手。

maven-assembly-plugin

http://maven.apache.org/plugins/maven-assembly-plugin/

maven-assembly-plugin的用途是制作项目分发包,该分发包可能包括了项目的可运行文件、源码、readme、平台脚本等等。

maven-assembly-plugin支持各种主流的格式如zip、tar.gz、jar和war等,详细打包哪些文件是高度可控的,比如用户能够按文件级别的粒度、文件集级别的粒度、模块级别的粒度、以及依赖级别的粒度控制打包,此外,包括和排除配置也是支持的。maven-assembly-plugin要求用户使用一个名为assembly.xml的元数据文件来表述打包,它的single目标能够直接在命令行调用。也能够被绑定至生命周期。

maven-dependency-plugin

http://maven.apache.org/plugins/maven-dependency-plugin/

maven-dependency-plugin最大的用途是帮助分析项目依赖,dependency:list可以列出项目终于解析到的依赖列表,dependency:tree能进一步的描绘项目依赖树,dependency:analyze可以告诉你项目依赖潜在的问题,假设你有直接使用到的却未声明的依赖,该目标就会发出警告。maven-dependency-plugin还有非常多目标帮助你操作依赖文件,比如dependency:copy-dependencies能将项目依赖从本地Maven仓库拷贝到某个特定的目录以下。

maven-enforcer-plugin

http://maven.apache.org/plugins/maven-enforcer-plugin/

在一个稍大一点的组织或团队中。你无法保证全部成员都熟悉Maven,那他们做一些比較愚蠢的事情就会变得非常正常,比如给项目引入了外部的SNAPSHOT依赖而导致构建不稳定,使用了一个与大家不一致的Maven版本号而常常抱怨构建出现诡异问题。maven-enforcer-plugin可以帮助你避免之类问题,它同意你创建一系列规则强制大家遵守。包含设定Java版本号、设定Maven版本号、禁止某些依赖、禁止SNAPSHOT依赖。仅仅要在一个父POM配置规则。然后让大家继承。当规则遭到破坏的时候,Maven就会报错。除了标准的规则之外,你还可以扩展该插件。编写自己的规则。maven-enforcer-plugin的enforce目标负责检查规则。它默认绑定到生命周期的validate阶段。

maven-help-plugin

http://maven.apache.org/plugins/maven-help-plugin/

maven-help-plugin是一个小巧的辅助工具,最简单的help:system能够打印全部可用的环境变量和Java系统属性。

help:effective-pom和help:effective-settings最为实用,它们分别打印项目的有效POM和有效settings,有效POM是指合并了全部父POM(包含Super
POM)后的XML。当你不确定POM的某些信息从何而来时,就能够查看有效POM。

有效settings同理,特别是当你发现自己配置的settings.xml没有生效时,就能够用help:effective-settings来验证。此外,maven-help-plugin的describe目标能够帮助你描写叙述不论什么一个Maven插件的信息,还有all-profiles目标和active-profiles目标帮助查看项目的Profile。

maven-release-plugin

http://maven.apache.org/plugins/maven-release-plugin/

maven-release-plugin的用途是帮助自己主动化项目版本号公布,它依赖于POM中的SCM信息。release:prepare用来准备版本号公布,详细的工作包含检查是否有未提交代码、检查是否有SNAPSHOT依赖、升级项目的SNAPSHOT版本号至RELEASE版本号、为项目打标签等等。release:perform则是签出标签中的RELEASE源代码,构建并公布。

版本号公布是很琐碎的工作,它涉及了各种检查,并且由于该工作不过偶尔须要,因此手动操作很easy遗漏一些细节,maven-release-plugin让该工作变得很高速简便,不易出错。maven-release-plugin的各种目标通常直接在命令行调用,由于版本号公布显然不是日常构建生命周期的一部分。

我们都知道Maven本质上是一个插件框架,它的核心并不运行不论什么详细的构建任务。全部这些任务都交给插件来完毕,比如编译源代码是由maven- compiler-plugin完毕的。

进一步说,每一个任务相应了一个插件目标(goal),每一个插件会有一个或者多个目标,比如maven- compiler-plugin的compile目标用来编译位于src/main/java/文件夹下的主源代码,testCompile目标用来编译位于src/test/java/文件夹下的測试源代码。

用户能够通过两种方式调用Maven插件目标。第一种方式是将插件目标与生命周期阶段(lifecycle phase)绑定,这样用户在命令行仅仅是输入生命周期阶段而已,比如Maven默认将maven-compiler-plugin的compile目标与compile生命周期阶段绑定。因此命令mvn compile实际上是先定位到compile这一生命周期阶段,然后再依据绑定关系调用maven-compiler-plugin的compile目标。

另外一种方式是直接在命令行指定要运行的插件目标。比如mvn
archetype:generate 就表示调用maven-archetype-plugin的generate目标。这样的带冒号的调用方式与生命周期无关。

认识上述Maven插件的基本概念能帮助你理解Maven的工作机制。只是要想更高效率地使用Maven。了解一些经常使用的插件还是非常有必要的,这能够帮助你避免一不小心又一次发明*。多年来Maven社区积累了大量的经验,并随之形成了一个成熟的插件生态圈。Maven官方有两个插件列表,第一个列表的GroupId为org.apache.maven.plugins,这里的插件最为成熟,详细地址为:http://maven.apache.org/plugins/index.html

第二个列表的GroupId为org.codehaus.mojo,这里的插件没有那么核心,但也有不少十分实用。其地址为:http://mojo.codehaus.org/plugins.html

接下来笔者依据自己的经验介绍一些最经常使用的Maven插件,在不同的环境下它们各自都有其出色的表现,熟练地使用它们能让你的日常构建工作事半功倍。

本文为下半部分。(上半部分内容參见Maven实战(七)——经常使用Maven插件介绍(上)

maven-resources-plugin

http://maven.apache.org/plugins/maven-resources-plugin/

为了使项目结构更为清晰,Maven差别对待Java代码文件和资源文件。maven-compiler-plugin用来编译Java代码。maven-resources-plugin则用来处理资源文件。默认的主资源文件文件夹是src/main/resources。非常多用户会须要加入额外的资源文件文件夹。这个时候就能够通过配置maven-resources-plugin来实现。此外,资源文件过滤也是Maven的一大特性。你能够在资源文件里使用${propertyName}形式的Maven属性,然后配置maven-resources-plugin开启对资源文件的过滤,之后就能够针对不同环境通过命令行或者Profile传入属性的值,以实现更为灵活的构建。

maven-surefire-plugin

http://maven.apache.org/plugins/maven-surefire-plugin/

可能是因为历史的原因,Maven 2/3中用于运行測试的插件不是maven-test-plugin。而是maven-surefire-plugin。事实上大部分时间内。仅仅要你的測试类遵循通用的命令约定(以Test结尾、以TestCase结尾、或者以Test开头)。就差点儿不用知晓该插件的存在。

然而在当你想要跳过測试、排除某些測试类、或者使用一些TestNG特性的时候。了解maven-surefire-plugin的一些配置选项就非常实用了。比如 mvn
test -Dtest=FooTest 这样一条命令的效果是仅执行FooTest測试类。这是通过控制maven-surefire-plugin的test參数实现的。

build-helper-maven-plugin

http://mojo.codehaus.org/build-helper-maven-plugin/

Maven默认仅仅同意指定一个主Java代码文件夹和一个測试Java代码文件夹,尽管这事实上是个应当尽量遵守的约定,但偶尔你还是会希望可以指定多个源代码文件夹(比如为了应对遗留项目),build-helper-maven-plugin的add-source目标就是服务于这个目的。通常它被绑定到默认生命周期的generate-sources阶段以加入额外的源代码文件夹。须要强调的是。这样的做法还是不推荐的,由于它破坏了 Maven的约定。并且可能会遇到其它严格遵守约定的插件工具无法正确识别额外的源代码文件夹。

build-helper-maven-plugin的还有一个很实用的目标是attach-artifact。使用该目标你能够以classifier的形式选取部分项目文件生成附属构件。并同一时候install到本地仓库。也能够deploy到远程仓库。

exec-maven-plugin

http://mojo.codehaus.org/exec-maven-plugin/

exec-maven-plugin非常好理解,顾名思义。它能让你执行不论什么本地的系统程序,在某些特定情况下。执行一个Maven外部的程序可能就是最简单的问题解决方式,这就是exec:exec的用途。当然。该插件还同意你配置相关的程序执行參数。

除了exec目标之外,exec-maven-plugin还提供了一个java目标,该目标要求你提供一个mainClass參数,然后它可以利用当前项目的依赖作为classpath。在同一个JVM中执行该mainClass。有时候。为了简单的演示一个命令行Java程序,你可以在POM中配置好exec-maven-plugin的相关执行參数,然后直接在命令执行 mvn
exec:java 以查看执行效果。

jetty-maven-plugin

http://wiki.eclipse.org/Jetty/Feature/Jetty_Maven_Plugin

在进行Web开发的时候,打开浏览器相应用进行手动的測试差点儿是无法避免的,这样的測试方法通常就是将项目打包成war文件,然后部署到Web容器中,再启动容器进行验证,这显然十分耗时。

为了帮助开发人员节省时间,jetty-maven-plugin应运而生,它全然兼容 Maven项目的文件夹结构。可以周期性地检查源文件。一旦发现变更后自己主动更新到内置的Jetty Web容器中。做一些基本配置后(比如Web应用的contextPath和自己主动扫描变更的时间间隔)。你仅仅要运行 mvn
jetty:run ,然后在IDE中改动代码,代码经IDE自己主动编译后产生变更,再由jetty-maven-plugin侦測到后更新至Jetty容器,这时你就能够直接測试Web页面了。须要注意的是,jetty-maven-plugin并非宿主于Apache或Codehaus的官方插件。因此使用的时候须要额外的配置settings.xml的pluginGroups元素,将org.mortbay.jetty这个pluginGroup增加。

versions-maven-plugin

http://mojo.codehaus.org/versions-maven-plugin/

非常多Maven用户遇到过这样一个问题,当项目包括大量模块的时候。为他们集体更新版本号就变成一件烦人的事情,究竟有没有自己主动化工具能帮助完毕这件事情呢?(当然你能够使用sed之类的文本操作工具,只是不在本文讨论范围)答案是肯定的,versions-maven- plugin提供了非常多目标帮助你管理Maven项目的各种版本号信息。比如最经常使用的,命令 mvn versions:set -DnewVersion=1.1-SNAPSHOT 就能帮助你把全部模块的版本号更新到1.1-SNAPSHOT。该插件还提供了其它一些非常实用的目标,display-dependency-
updates能告诉你项目依赖有哪些可用的更新。类似的display-plugin-updates能告诉你可用的插件更新。然后use- latest-versions能自己主动帮你将全部依赖升级到最新版本号。最后,假设你对所做的更改惬意。则能够使用 mvn versions:commit 提交,不惬意的话也能够使用 mvn
versions:revert 进行撤销。

小结

本文介绍了一些最经常使用的Maven插件。这里指的“经常使用”是指经常须要进行配置的插件。其实我们用Maven的时候非常多其他插件也是必须的,比如默认的编译插件maven-compiler-plugin和默认的打包插件maven-jar-plugin,但由于非常少须要对它们进行配置。因此不在本文讨论范围。了解经常使用的Maven插件能帮助你事倍功半地完毕项目构建任务。反之你就可能会由于经常遇到一些难以解决的问题而感到沮丧。本文介绍的插件基本能覆盖大部分Maven用户的日常使用须要。假设你真有非常特殊的需求。自行编写一个Maven插件也不是难事,更何况还有这么多开放源码的插件供你參考。

本文的这个插件列表并非一个完整列表。读者有兴趣的话也能够去细致浏览一下Apache和Codehaus Mojo的Maven插件列表,以的到一个更为全面的认识。

最后,在线的Maven仓库搜索引擎如http://search.maven.org/也能帮助你高速找到自己感兴趣的Maven插件。

原文地址:http://www.infoq.com/cn/news/2011/04/xxb-maven-7-plugin