这是一个Maven提高篇的系列,包含有以下文章:

  1. Maven提高篇系列之(一)——多模块 vs 继承
  2. Maven提高篇系列之(二)——配置Plugin到某个Phase(以Selenium集成测试为例)
  3. Maven提高篇系列之(三)——使用自己的Repository(Nexus)
  4. Maven提高篇系列之(四)——使用Profile
  5. Maven提高篇系列之(五)——处理依赖冲突
  6. Maven提高篇系列之(六)——编写自己的Plugin(本系列完)

在本系列的上一篇文章中,我们讲到了如何处理依赖冲突,在本文中,我们将讲到如何编写自己的Plugin。

Maven就其本身来说只是提供一个执行环境,它并不知道需要在项目上完成什么操作,真正操作项目的是插件(plugin),比如编译Java有Compiler插件,打包有Jar插件等。所以要让Maven完成各种各样的任务,我们需要配置不同的插件,甚至自己编写插件。

你可能要问了:“我并没有配置什么插件啊,照样能编译打包。”这是因为Maven在默认情况下已经给我们配置了一些常用的插件,上面的Compiler和Jar便在这些插件之列。要查看Maven的默认插件,我们需要找到Super Pom,在笔者的电脑上,Super Pom位于M2_HOME/lib/maven-2.2.1-uber.jar文件中,文件名为pom-4.0.0.xml,里面包含了Maven所有的默认插件:

<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.3</version>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-2</version>
</plugin>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>2.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
</plugin>
......
</plugins>
</pluginManagement>

任何Maven工程默认都继承自这个Super Pom,你也可以在自己的项目中执行:

mvn help:effective-pom

来查看包括继承内容的整个pom文件,其中便包含了从Super Pom继承下来的内容。

和其他Maven项目一样,Maven的插件也是一种packaging类型(类型为maven-plugin),也拥有groupId,artifactId和version。简单地讲,一个Maven插件包含了一些列的goal,每一个goal对应于一个Mojo类(Maven Old Java Object,命名来自于Pojo),每个Mojo都需要实现org.apache.maven.plugin.Mojo接口,该接口定义了一个execute方法,在开发插件时,你的任务就是实现这个execute方法。

(一)创建自己的插件

接下来,我们来实现一个Maven插件,该插件输出项目的build目录信息。请下载本文的github源代码:https://github.com/davenkin/demo-maven-plugin

先通过archetype创建一个Maven插件工程:

 mvn archetype:generate \
-DgroupId=me.davenkin \
-DartifactId=demo-maven-plugin \
-DarchetypeGroupId=org.apache.maven.archetypes \
-DarchetypeArtifactId=maven-archetype-mojo

此时打开工程中的pom.xml文件,你可以看到该工程的packaging类型:

<packaging>maven-plugin</packaging>

向工程中添加一个Mojo类:

/**
* @goal buildinfo
* @phase pre-integration-test
*/
public class BuildInfoMojo extends AbstractMojo { /**
* @parameter expression="${project}"
* @readonly
*/
private MavenProject project; /**
* @parameter expression="${buildinfo.prefix}"
* default-value="+++"
*/
private String prefix; public void execute() throws MojoExecutionException {
Build build = project.getBuild();
String outputDirectory = build.getOutputDirectory();
String sourceDirectory = build.getSourceDirectory();
String testOutputDirectory = build.getTestOutputDirectory();
String testSourceDirectory = build.getTestSourceDirectory();
getLog().info("\n==========================\nProject build info:");
String[] info = {outputDirectory, sourceDirectory, testOutputDirectory, testSourceDirectory};
for (String item : info) {
getLog().info("\t" + prefix + " " + item);
}
getLog().info("=======================");
}
}

在上面的代码中,“@goal buildinfo”表示该Mojo对应的goal的名字为buildinfo(在调用该goal时需要给出它的名字),“@phase   pre-integration-test”表示该Mojo默认被绑定在了pre-integration-test阶段。之后的:

/**
* @parameter expression="${project}"
* @readonly
*/
private MavenProject project;

表示该插件持有一个到MavenProject的引用,当客户方在执行该插件时,这里的project字段便表示客户工程。这里我们并没有对project进行初始化,但是“@parameter expression="${project}"”中的${project}即表示当前的客户工程,Maven在运行时会通过依赖注入自动将客户工程对象赋给project字段(请参考Maven自己的IoC容器Plexus)。此外,我们还声明了一个prefix字段,该字段表示对输出的各行加上prefix前缀字符串,默认为“+++”(加入prefix字段主要用于演示对插件参数的配置,这里的project和prefix都表示插件参数,我们可以在客户方重新配置这些参数)。

由于上面的代码用到了MavenProject类,我们还需要在该插件工程的pom.xml中加入以下依赖:

<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-project</artifactId>
<version>2.2.1</version>
</dependency>

在执行了“mvn clean install“之后,我们便可以通过一下命令调用该Mojo:

mvn me.davenkin:demo-maven-plugin:1.0-SNAPSHOT:buildinfo

笔者在当前的插件工程中执行该命令输出结果如下:

......

==========================

Project build info:

[INFO] +++   /home/davenkin/Desktop/demo-maven-plugin/demo-maven-pugin/target/classes

[INFO] +++   /home/davenkin/Desktop/demo-maven-plugin/demo-maven-pugin/src/main/java

[INFO] +++   /home/davenkin/Desktop/demo-maven-plugin/demo-maven-pugin/target/test-classes

[INFO] +++   /home/davenkin/Desktop/demo-maven-plugin/demo-maven-pugin/src/test/java

[INFO] =======================

......

以上的”+++“便表示prefix的默认属性值,后跟各个build目录。我们也可以通过"-D"参数为prefix重新赋值:

mvn me.davenkin:demo-maven-plugin:1.0-SNAPSHOT:buildinfo -Dbuildinfo.prefix=---

以上我们用"---"代替了默认的"+++"。

你可能注意到,为了调用该插件的buildinfo这个goal,我们需要给出该插件的所有坐标信息,包括groupId,artifactId和version号。你可能之前已经执行过"mvn eclipase:eclipase"或"mvn idea:idea"这样简洁的命令,让我们也来将自己的插件调用变简单一点。

要通过简单别名的方式调用Maven插件,我们需要做到以下两点:

  1. 插件的artifactId应该遵循***-maven-plugin或maven-***-plugin命名规则,对于本文中的插件,我们已经遵循了。(当然不遵循也是可以的,此时你需要使用Maven Plugin Plugin来设置goalPrefix,此时就不见得为“demo”了)

  2. 需要将插件的groupId放在Maven默认的插件搜寻范围之内,默认情况下Maven只会在org.apache.maven.plugins和org.codehaus.mojo两个groupId下搜索插件,要让Maven同时搜索我们自己的groupId,我们需要在~/.m2/settings.xml中加入:

    <pluginGroups>
    <pluginGroup>me.davenkin</pluginGroup>
    </pluginGroups>

在达到以上两点之后,我们便可以通过以下命令来调用自己的插件了:

mvn demo:buildinfo

(二)在别的项目使用插件

要在别的项目中应用插件也是简单的,我们只需要在该项目的pom.xml文件中声明该插件的即可:

<plugin>
<groupId>me.davenkin</groupId>
<artifactId>demo-maven-plugin</artifactId>
<version>1.0-SNAPSHOT</version>
<configuration>
<prefix>---</prefix>
</configuration> <executions>
<execution>
<id>buildinfo</id>
<phase>process-sources</phase>
<goals>
<goal>buildinfo</goal>
</goals>
</execution>
</executions>
</plugin>

在上面的配置中,我们将demo-maven-plugin插件的buildinfo绑定在了process-sources阶段,并将prefix参数该为了"---",这样在执行"mvn clean install" 时,该插件的输出内容将显示在终端。另外,我们可以通过设置属性的方式为demo-maven-plugin的prefix参数赋值,在pom.xml中加入一下property:

<properties>
<buildinfo.prefix>---</buildinfo.prefix>
</properties>

此时,去掉plugin配置中的:

<configuration>
<prefix>---</prefix>
</configuration>

运行"mvn clean install",输出效果和之前一样。

Maven提高篇系列之(六)——编写自己的Plugin(本系列完)的更多相关文章

  1. Maven提高篇系列之(五)——处理依赖冲突

    这是一个Maven提高篇的系列,包含有以下文章: Maven提高篇系列之(一)——多模块 vs 继承 Maven提高篇系列之(二)——配置Plugin到某个Phase(以Selenium集成测试为例) ...

  2. Maven提高篇系列之(四)——使用Profile

    这是一个Maven提高篇的系列,包含有以下文章: Maven提高篇系列之(一)——多模块 vs 继承 Maven提高篇系列之(二)——配置Plugin到某个Phase(以Selenium集成测试为例) ...

  3. Maven提高篇系列之(三)——使用自己的Repository(Nexus)

    这是一个Maven提高篇的系列,包含有以下文章: Maven提高篇系列之(一)——多模块 vs 继承 Maven提高篇系列之(二)——配置Plugin到某个Phase(以Selenium集成测试为例) ...

  4. Maven提高篇系列之(二)——配置Plugin到某个Phase(以Selenium集成测试为例)

    这是一个Maven提高篇的系列,包含有以下文章: Maven提高篇系列之(一)——多模块 vs 继承 Maven提高篇系列之(二)——配置Plugin到某个Phase(以Selenium集成测试为例) ...

  5. Maven提高篇系列之(一)——多模块 vs 继承

    这是一个Maven提高篇的系列,包含有以下文章: Maven提高篇系列之(一)——多模块 vs 继承 Maven提高篇系列之(二)——配置Plugin到某个Phase(以Selenium集成测试为例) ...

  6. Java提高篇(二六)-----hashCode

          在前面三篇博文中LZ讲解了(HashMap.HashSet.HashTable),在其中LZ不断地讲解他们的put和get方法,在这两个方法中计算key的hashCode应该是最重要也是最 ...

  7. Maven提高篇系列之五——处理依赖冲突

    个人分类: Maven 不知道你在使用Maven时是否遇到过诸如"NoSuchMethodError"或"ClassNotFoundException"之类的问 ...

  8. chessy 提高篇系列 阅读笔记

    java提高篇(一)—–理解java的三大特性之封装 封装的好处, 汇聚属性和方法 减少修改对 其他处的影响 控制get和set方法. java提高篇(二)—–理解java的三大特性之继承 继承的好处 ...

  9. Java提高篇(三三)-----Map总结

    在前面LZ详细介绍了HashMap.HashTable.TreeMap的实现方法,从数据结构.实现原理.源码分析三个方面进行阐述,对这个三个类应该有了比较清晰的了解,下面LZ就Map做一个简单的总结. ...

随机推荐

  1. dojo/query源码解析

    dojo/query模块是dojo为开发者提供的dom查询接口.该模块的输出对象是一个使用css选择符来查询dom元素并返回NodeList对象的函数.同时,dojo/query模块也是一个插件,开发 ...

  2. ECMAScript 6中的let和const关键词

    ECMAScript 6中多了两个定义变量的关键词,一个是let,另一个是const,后者顾名思义就是常量定义,前者的作用域范围是块级的. 一般写过js的童鞋都知道,同其他语言一样,JS中的变量作用域 ...

  3. SmartImageView

    == public class SmartImageView extends ImageView { public SmartImageView(Context context) { super(co ...

  4. Visual Studio 2015速递(2)——提升效率和质量(VS2015核心竞争力)

    系列文章 Visual Studio 2015速递(1)——C#6.0新特性怎么用 Visual Studio 2015速递(2)——提升效率和质量(VS2015核心竞争力) Visual Studi ...

  5. 每天一个linux命令(56):netstat命令

    netstat命令​用于显示与IP.TCP.UDP和ICMP协议相关的统计数据,一般用于检验本机各端口的网络连接情况.netstat是在内核中访问网络及相关信息的程序,它能提供TCP连接,TCP和UD ...

  6. Thrift架构~thrift中间语言的认识(只有它什么都不是,它才有可能什么都是)

    中间语言是我为thrift语言起的名字,呵呵,为什么叫它中间语言呢,其实意思很简单,就是说,它只是一个过程,而不是一个最终的结果,而结果需要这个中间过程的影响,没有中间语言,结果语言也不能产生,在th ...

  7. Python学习--06切片

    Python里提供了切片(Slice)操作符获取列表里的元素. 示例: >>> L = [1,2,3,4,5] # 取前2个元素,传统方法 >>> [L[0],L[ ...

  8. Android开发学习之路-Android Design Support Library使用(CoordinatorLayout的使用)

    效果图: 上面的这个图有两个效果是,一个是顶部的图片,在上滑之后会隐藏起来并且显示出一个ToolBar(ToolBar类似于ActionBar,但是只有ToolBar是兼容Material Desig ...

  9. Atitit.软件中见算法 程序设计五大种类算法

    Atitit.软件中见算法 程序设计五大种类算法 1. 算法的定义1 2. 算法的复杂度1 2.1. Algo cate2 3. 分治法2 4. 动态规划法2 5. 贪心算法3 6. 回溯法3 7. ...

  10. win2003 64位系统IIS6.0 32位与64位间切换

    ASP.NET 1.1,32 位版本 要运行 32 位版本的 ASP.NET 1.1,按照以下步骤操作: 1.单击“开始”,单击“运行”,键入 cmd,然后单击“确定”. 2.键入以下命令启用 32 ...