这是一个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. Ubuntu Server 15.04的安装

    U盘启动工具的制作就跟Windows系统以及Linux各版本的desktop版不同,用的工具也是我第一次见到的“Win32_Disk_Imager”(点击下载) 安装过程请参考:http://www. ...

  2. Centos6下安装Mono和Jexus部署ASP.NET应用程序(纯干货)

    一.服务器 腾讯云VPS,Centos6.6系统 二.安装 1.yum升级 yum –y update 2.安装Mono所需要的库 yum -y install gcc gcc-c++ bison p ...

  3. 软将工程课设day1与day2

    在稍迟的时候,收集了三份用户体验,自己编辑整理之后上交于组. 和老师确定了一下每日的工作流程与需要提交的任务. 与组讨论了软件优化方向,包括整理收集到的“反馈信息”.“额外需求信息”.“体验信息”.

  4. dojo/dom-style样式操作学习笔记

    基础总结 一个元素的样式信息由三个来源根据层叠规则确定.三个来源分别是: 由DOM元素style特性设置的内联样式 由style元素中嵌入的样式规则 由link元素引入的外部样式表 元素的样式 任何支 ...

  5. iOS-数据持久化-SQlite3

    SQLite3简单介绍 1.ios中数据的存储方式 (1)Plist(NSArray\NSDictionary) (2)Preference(偏好设置\NSUserDefaults) (3)NSCod ...

  6. 用javascript动态创建并提交表单form,表格table

    <script> //helper function to create the formfunction getNewSubmitForm(){ var submitForm = doc ...

  7. javascript基础语法——变量和标识符

    × 目录 [1]定义 [2]命名规则 [3]声明[4]特性[5]作用域[6]声明提升[7]属性变量 前面的话 关于javascript,第一个比较重要的概念是变量,变量的工作机制是javascript ...

  8. double保持精度,防止小数点后数字的丢失的小方法

    一般情况下,输入带小数点的字面值,编译器会把它解析成double 类型. 例如:一个字面值被直接放到代码中,由于带小数点所以,默认值为double类型   输出结果是:1.12345678912345 ...

  9. Android强制设定横屏时,SurfaceView一直黑屏

    接着上一个问题,解决了SurfaceView闪屏问题之后(http://www.cnblogs.com/Joanna-Yan/p/4829325.html),又有了一个新的问题.现在我想设置含有fra ...

  10. Android自定义ImageView圆形头像

    效果图: 代码如下: RoundImageView.java import cn.comnav.evaluationsystem.R; import android.content.Context; ...