Maven进阶二:常用Maven插件介绍

前言

Maven本质上是一个插件框架,它的核心并不执行任何具体的构建任务,所有这些任务都交给插件来完成,例如编译源代码是由maven-compiler-plugin完成的。

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

用户可以通过两种方式调用Maven插件目标。

  1. 将插件目标与生命周期阶段(lifecyclephase)绑定,这样用户在命令行只是输入生命周期阶段而已,例如Maven默认将maven-compiler-plugin的compile目标与compile生命周期阶段绑定,因此命令mvn compile实际上是先定位到compile这一生命周期阶段,然后再根据绑定关系调用maven-compiler-plugin的compile目标。

  2. 直接在命令行指定要执行的插件目标,例如mvn archetype:generate 就表示调用maven-archetype-plugin的generate目标,这种带冒号的调用方式与生命周期无关。

认识上述Maven插件的基本概念能帮助你理解Maven的工作机制,不过要想更高效率地使用Maven,了解一些常用的插件还是很有必要的,这可以帮助你避免一不小心重新发明轮子。

多年来Maven社区积累了大量的经验,并随之形成了一个成熟的插件生态圈。Maven官方有两个插件列表:

  1. 第一个列 表的GroupId为org.apache.maven.plugins,这里的插件最为成熟,具体地址为:http://maven.apache.org/plugins/index.html。
  2. 第二个列表的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生成一个很简单的项目骨架,帮助开发者快速上手。

可能也有人看到一些文档写了mvn archetype:create,但实际上create目标已经被弃用了,取而代之的是generate目标,该目标使用交互式的方式提示用户输入必要的信息以创建项目,体验更好。

maven-archetype-plugin还有一些其他目标帮助用户自己定义项目原型,例如你由一个产品需要交付给很多客户进行二次开发,你就可以为 他们提供一个Archtype,帮助他们快速上手。

最佳实践:
实际应用中,项目组(或者部门/公司)会有自己的私服,因此以下的介绍前提条件是配有自己的私服。

  1. 选择模版项目,生成原型
    在选择作为模板的Maven工程目录下执行:

    1
    mvn clean archetype:create-from-project

    此时项目的Archetype已经生成,位于${basedir}/target/generated-sources/archetype/目录下。

  2. 将Archetype上传到私服,共享给其他人使用(需要有deploy权限和scm配置)。
    到${basedir}/target/generated-sources/archetype/目录下执行命令:

    1
    mvn deploy
将该原型上传到私服,此时前期工作完成,以后可以使用该原型生成项目骨架。
  1. 使用Archetype生成项目骨架
    任意目录下,执行命令:
    1
    2
    3
    4
    5
    6
    7
    mvn archetype:generate
    -DinteractiveMode=false
    -DarchetypeGroupId=com.ktr
    -DarchetypeArtifactId=java-project-template-archetype
    -DarchetypeVersion=1.1-SNAPSHOT
    -DgroupId=com.ktr
    -DartifactId=ktr-t

(命令应该在一行,为了方便查看,故分开多行)
(命令的参数省略了默认部分。命令参数的详细说明请见:官网)

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-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-source-plugin

官网:
http://maven.apache.org/plugins/maven-source-plugin/

说明:
一个Maven项目只生成一个主构件,当需要生成其他附属构件的时候,就需要用上classifier。

源码包和Javadoc包就是附属构件的极佳例子。它们有着广泛的用途,尤其是源码包,当你使用一个第三方依赖的时候,有时候会希望在IDE中直接进入该依赖的源码查看其实现的细节,如果该依赖将源码包发布到了Maven仓库,那么像Eclipse就能通过m2eclipse插件解析下载源码包并关联到你的项目中,十分方便。
由于生成源码包是极其常见的需求,因此Maven官方提供了一个插件来帮助用户完成这个任务:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.1.2</version>
<executions>
<execution>
<id>attach-sources</id>
<phase>verify</phase>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>

类似的,生成Javadoc包只需要配置插件如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.7</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>

maven-shade-plugin

官网:
http://maven.apache.org/plugins/maven-shade-plugin/

说明
除了前面常规JAR包、WAR包,源码包和Javadoc包,另一种常被用到的包是在命令行可直接运行的CLI(Command Line)包。默认Maven生成的JAR包只包含了编译生成的.class文件和项目资源文件,而要得到一个可以直接在命令行通过java命令运行的JAR文件,还要满足两个条件:

  • JAR包中的/META-INF/MANIFEST.MF元数据文件必须包含Main-Class信息。
  • 项目所有的依赖都必须在Classpath中。

Maven有好几个插件能帮助用户完成上述任务,不过用起来最方便的还是maven-shade-plugin,它可以让用户配置Main-Class的值,然后在打包的时候将值填入/META-INF/MANIFEST.MF文件。关于项目的依赖,它很聪明地将依赖JAR文件全部解压后,再将得到的.class文件连同当前项目的.class文件一起合并到最终的CLI包中,这样,在执行CLI JAR文件的时候,所有需要的类就都在Classpath中了。

补充:
实际运用实例:当项目应用dubbo框架实现分布式系统时。需要引入多个dubbo的依赖。而dubbo在github上提供了源码。我们完全可以利用该插件将dubbo的多个组件打包成一个jar包。在自己的Maven项目中依赖该jar包,并使用下述‘maven-dependency-plugin’解压后即可正常使用

maven-dependency-plugin

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

说明:
maven-dependency-plugin最大的用途是帮助分析项目依赖。

  1. dependency:list能够列出项目最终解析到的依赖列表。
  2. dependency:tree能进一步的描绘项目依赖树。
  3. dependency:analyze可以告诉你项目依赖潜在的问题,如果你有直接使用到的却未声明的依赖,该目标就会发出警告。
  4. maven-dependency-plugin还有很多目标帮助你操作依赖文件,例如dependency:copy-dependencies能将项目依赖从本地Maven仓库复制到某个特定的文件夹下面。

maven-release-plugin

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

说明:
maven-release-plugin的用途是帮助自动化项目版本发布,它依赖于POM中的SCM信息。

  • release:prepare用来准备版本发布,具体的工作包括检查是否有未提交代码、检查是否有SNAPSHOT依赖、升级项目的SNAPSHOT版本至RELEASE版本、为项目打标签等等。
  • release:perform则是签出标签中的RELEASE源码,构建并发布。

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

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加入。


小结

本文介绍了一些最常用的Maven插件,这里指的“常用”是指经常需要进行配置的插件,事实上我们用Maven的时候很多其它插件也是必须的,例如 默认的编译插件maven-compiler-plugin和默认的打包插件maven-jar-plugin,但因为很少需要对它们进行配置,因此不在本文讨论范围。

了解常用的Maven插件能帮助你事倍功半地完成项目构建任务,反之你就可能会因为经常遇到一些难以解决的问题而感到沮丧。

本文介绍的插件 基本能覆盖大部分Maven用户的日常使用需要,如果你真有非常特殊的需求,自行编写一个Maven插件也不是难事,更何况还有这么多开放源代码的插件供 你参考。

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

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


参考资料

坚持原创技术分享,您的支持将鼓励我继续创作!