`

maven插件开发

阅读更多

一 maven 框架

    maven官方文档介绍Apache Maven 2.2.x是一个项目开发和集成的工具,它建立在项目模型对象(PMO)基础之上,所有构建、依赖管理、文档创建、站点发布, 分发都在pom.xml文件中控制. Maven是可以用插件来扩展。它的框架如下:(2.2.x)

maven框架

 

 

maven3.x框架结构如下
maven3.x

 

二 Maven属性

      使用插件来扩展maven功能,必须先了解maven可访问的属性,maven属性在前一小节已经有过简单介绍,这里再展开讨论下。

      在pom.xml中可以使用Maven属性,格式为${属性名},在Maven项目中可以使用隐式属性如project.*(应用pom文件中project属性),setting.*(访问setting.xml文件中属性),env.*(访问环境变量属性,如path和MAVEN_HOME),系统属性(通过java中System.getProperty()能拿到的属性)。下面分别介绍这些属性:

      1 项目属性

         当你使用该隐式变量引用属性的时候,你实际上正在使用简单的点标记来引用Model对象的一个bean属性。例如,当你引用0.6-SNAPSHOT的时候,你实际上是在调用暴露出来的Model对象实例的getVersion()方法。任何在Maven POM 中的东西都可以用属性来引用,比如pom.xml中有

 

<groupId>org.sonatype.group1</groupId>
<artifactId>sibling-project</artifactId>
<version>0.6-SNAPSHOT</version>

 project.groupId 和 project.version 分别为org.sonatype.group1和0.6-SNAPSHOT

 

在一个POM中有数百的属性可以引用,具体可以参考pom的完整结构http://maven.apache.org/ref/2.2.1/maven-model/apidocs/index.html,查看org.apache.maven.model这个类的javadoc文档,能够找到想要的项目属性。

 

   2 setting属性

    任何Maven本地Settings文件的属性都可以被引用,该文件通常位于~/.m2/settings.xml。这个文件包含了用户特定的配置,如本地仓库的位置,以及由某个特定用户配置的服务器,profile,和镜像,setting的具体属性可以参考http://maven.apache.org/ref/2.2.1/maven-settings/index.html中Maven Settings Model的javadoc

 

   3 环境变量属性

    env.PATH, env.HOME, env.JAVA_HOME, env.MAVEN_HOME

    虽然他们都是可用的,但如果你有选择,你更应该使用Java系统属性

 

    4 Java系统属性

    Maven暴露所有来自于java.lang.System的属性。任何你能从System.getProperty()获取的属性都能以Maven属性的形式引用

java.version Java运行环境版本 java.vendor Java运行环境供应商
java.vendor.url Java供应商URL java.home Java安装目录
java.vm.specification.version Java虚拟机规格说明版本 java.vm.specification.vendor  Java虚拟机规格说明供应商
java.vm.specification.name Java虚拟机规格说明名称 java.vm.version Java虚拟机实现版本
java.vm.vendor Java虚拟机实现供应商 java.vm.name Java虚拟机实现名称
java.specification.version Java运行环境规格说明版本 java.specification.vendor Java运行环境规格说明供应商
java.specification.name Java运行环境规格说明名称 java.class.version Java类格式版本号
java.class.path Java类路径 java.ext.dirs 扩展目录的路径
os.name 操作系统名称 os.arch 操作系统架构
os.version 操作系统版本 file.separator 文件分隔符(UNIX上是"/",Windows上是"\")
path.separator 路径分隔符(UNIX上是":",Windows上是";") line.separator  行分隔符(在UNIX和Windows上都是"\n")
user.name 用户帐户名称 user.home 用户home目录
user.dir 用户当前工作目录    

 

    5 用户定义属性

这类属性可以定义在POM或者Profile中,而这些在POM或者MavenProfile中设置的属性可以像任何其它Maven属性一样被引用。

<properties>
<arbitrary.property.a>This is some text</arbitrary.property.a>
<hibernate.version>3.3.0.ga</hibernate.version>
</properties>

 

<profiles>
<profile>
<id>some-profile</id>
<properties>
<arbitrary.property>This is some text</arbitrary.property>
</properties>
</profile>
</profiles>

 

 

在资源中引用属性,可以使用外部资源文件,如开启maven的filter过滤资源,默认maven的filter文件路径为src/main/filters/目录,也可以在pom中设置到其他路径,比如想用default.properties的属性替换掉资源文件里的占位符,目录路径为:



 

service.xml内容为:

<?xml version="1.0" encoding="UTF-8"?>
<service>
<!-- This URL was set by project version 0.6-SNAPSHOT -->
<url>${jdbc.url}</url>
<user>${jdbc.username}</user>
<password>${jdbc.password}</password>
</service>
</xml>

 

 default.properties内容为:

jdbc.url=jdbc:hsqldb:mem:mydb
jdbc.username=admin
jdbc.password=

 pom.xml filter设置为:

<project>
....
<properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
....
<build>
		<finalName>simple-webapp</finalName>
		<filters>
			<filter>src/main/filters/default.properties</filter>
		</filters>
		<resources>
			<resource>
				<directory>src/main/resources</directory>
				<filtering>true</filtering>
			</resource>
		</resources>		
	</build>
....
</project>

 

 开启资源过滤后(资源过滤默认是关闭的),运行mvn resources:resources后,target目录下target\classes\META-INF\service.xml占位符会被properties文件具体值替换掉。

 

 

三 maven 插件

 

1 反转控制(IOC)

Maven的心脏是一个名为Plexus的反转控制(IoC)框架,它是一个用来管理及关联组件的系统。用Java实现的IoC容器中,最重要的一个功能是称作依赖注入的机制。IoC的基本想法是将对象的创建和管理从代码中剥离,并将控制放到IoC框架手中。在一个面向接口编程的应用程序中使用依赖注入,你创建的组件可以不与任何特定的接口实现绑定。你的程序也针对接口编程并通过配置Plexus来将正确的实现连接到正确的组件。虽然你的代码都是与接口打交道,但你仍然可以通过一个定义组件的XML文件来获得类和组件相互依赖的信息。换句话说,你可以编写独立的组件,然后你可以通过一个XML文件来定义组件应当如何被装配在一起。在Plexus的情形中,定义系统组件的XML文档位于META-INF/plexus/components.xml。在一个Java IoC容器中,有很多中方法将依赖值注入到一个组件对象中:构造器,set方法,或者字段注入。虽然Plexus提供全部这三种依赖注入技术,Maven只使用其中的两种:字段注入和set方法注入。

      目前Spring是最流行的IoC容器。它影响了Java的“生态系统”,迫使如SunMicrosystems之类的公司让出更多的对于开源社区的控制,并通过提供一个更易插入的,面向组件的“总线”来帮助开发一些标准,当Maven被创建的时候,Spring并不是一个成熟的选项。最初的Maven提交者团队更熟悉Plexus因为正是他们发明了Plexus,因此他们决定使用Plexus做为Ioc容器。虽然它没有Spring Framework流行,但并不是说它的功能没那么强大。

     

2 插件

      一个Maven插件是包含了一个插件描述符和一个或者多个Mojo的Maven构件。一个Mojo可以被认为是Maven中的一个目标,每一个目标对应了一个Mojo。compiler:compile目标对应了Maven Compiler插件的CompilerMojo类,jar:jar目标对应了Maven Jar插件的JarMojo类。当你编写自己的插件的时候,你在一个单独的插件构件中将一组相互关联的Mojo(或者目标)归类。(Maven使用术语Mojo因为这是一个对于Pojo(Plan-oldJava Object)的玩笑),Mojo不仅仅是Maven中的一个目标,它是一个由Plexus管理的组件,可以引用其它Plexus组件。

 

1)插件描述符

Maven插件包含了一个告诉Maven各种Mojo和插件配置的路线图。这就是插件描述符,它位于JAR文件中的META-INF/maven/plugin.xml。当Maven载入一个插件的时候,它读取该XML文件,初始化并配置插件对象,使Mojo被包含在插件中,供Maven使用。当你编写自定义Maven插件的时候,你几乎不需要编写插件描述符。在构 建生命周期中,绑定到maven-plugin打包类型的生命周期目标显示,plugin:descriptor目标被绑定到了generate-resources生命周期阶段。该目标根据插件源码中的注解生成一个插件描述符,plugin.xml定义三部分内容:坐标信息、mojo声明、依赖声明。

description 该元素包含了插件的简短描述。
groupId, artifactId, version 就像Maven中的任何其它构件一样,插件也需要唯一的坐标
goalPrefix 该元素(目标前缀)用来设置某个特定插件用来引用目标的前缀
isolatedRealm 该遗留属性不再被Maven使用。它的存在是为了给旧的插件提供向后兼容性早期版本的Maven。使用它提供一种在单独ClassLoader中载入插件依赖的机制
inheritedByDefault 如果inheritedByDefault(缺省继承)被设置成true,所有在父项目配置的该插件的mojo会在子项目中生效inheritedByDefault没有被设置成true,那么定义在父项目中的目标执行不会被子项目继承
mojo配置  
goal 这是目标的名称。如果你在运行compiler:compile目标,compiler就是插件的goalPrefix,compile就是目标的名称。
description 目标的简要描述,当用户使用Help插件生成插件文档的时候,该描述会被显示
requiresDirectInvocation 如果你将其设置成true,那么该目标就只能由用户在命令行显示的执行。如果有人想要将该目标绑定到一个生命周期阶段,Maven会打印错误信息。该元素默认值是false。
requiresProject 指定该目标不能在项目外部运行。目标需要一个带有POM的项目。requiresProject默认的值为true。
requiresReports 如果你正创建一个插件,它依赖于报告,那么你就需要将requiresReports设置成true。例如,如果你创建一个插件用来聚合许多报告的信息,那么就需要将requiresReports设置成true。该元素默认的值为false。
aggregator 当Mojo描述符的aggregator设置成true的时候,那么该目标只会在Maven执行的时候运行一次,提供该配置是为了让开发人员能够对一系列构建进行总结;例如,创建一个插件来概述构建中所有项目的一类报告。一个aggregator设置成true的目标应该只在Maven构建的顶层项目中运行。aggregator默认值是false。
requiresOnline 指定当Maven在离线模式(-o命令行选项)的时候该目标不能运行,该元素默认值是false
inheritedByDefault 如果inheritedByDefault被设置成true,在父项目中配置的mojo就会同样在子项目中被继承
phase 如果用户没有为该目标绑定一个阶段,那么该元素定义一个mojo默认的阶段,若你没有指定phase元素,Maven就会要求用户在POM中显式的指定一个阶段
implementation 该元素告诉Maven需要为该Mojo初始化什么类,这是一个Plexus组件属性(在Plexus ComponentDescriptor 中定义)
language Maven Mojo默认的语言是java,该配置控制Plexus ComponentFactory初始化该Mojo组件
instantiationStrategy 该属性是一个Plexus组件配置属性,它告诉Plexus如何创建和管理组件实例,Maven中,所有mojo的instantiationStrategy都被配置成per-lookup,每次Maven从Plexus获取该mojo的时候,一个新的实例被创建
executionStrategy executionStrategy告诉Maven什么时候,怎样运行一个Mojo,once-per-session和always,是早期版本遗留的
parameters 该元素描述Mojo的所有参数。name,type,required,editable(是否允许在pom.xml中设置),description
configuration (为所有Mojo参数提供默认值)
requirements 一个mojo是一个由Plexus管理的组件,它就有机会引用Plexus管理的其它组件。该元素能让你定义对于其它Plexus组件的依赖
   
   

 

2)编写插件

a)创建插件项目:

mvn archetype:create -DgroupId=org.sonatype.plugins -DartifactId=first-maven-plugin -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-mojo

 

运行mvn install 后,可以打开jar包(或者class目录中META-INF\maven)下pugin.xml插件描述文件:

  <?xml version="1.0" encoding="UTF-8" ?> 
- <plugin>
  <description /> 
  <groupId>org.sonatype.plugins</groupId> 
  <artifactId>first-maven-plugin</artifactId> 
  <version>1.0-SNAPSHOT</version> 
  <goalPrefix>first</goalPrefix> 
  <isolatedRealm>false</isolatedRealm> 
  <inheritedByDefault>true</inheritedByDefault> 
- <mojos>
- <mojo>
  <goal>touch</goal> 
  <description>Goal which touches a timestamp file.</description> 
  <requiresDirectInvocation>false</requiresDirectInvocation> 
  <requiresProject>true</requiresProject> 
  <requiresReports>false</requiresReports> 
  <aggregator>false</aggregator> 
  <requiresOnline>false</requiresOnline> 
  <inheritedByDefault>true</inheritedByDefault> 
  <phase>process-sources</phase> 
  <implementation>org.sonatype.plugins.MyMojo</implementation> 
  <language>java</language> 
  <instantiationStrategy>per-lookup</instantiationStrategy> 
  <executionStrategy>once-per-session</executionStrategy> 
- <parameters>
- <parameter>
  <name>outputDirectory</name> 
  <type>java.io.File</type> 
  <required>true</required> 
  <editable>true</editable> 
  <description>Location of the file.</description> 
  </parameter>
  </parameters>
- <configuration>
  <outputDirectory implementation="java.io.File">${project.build.directory}</outputDirectory> 
  </configuration>
  </mojo>
  </mojos>
- <dependencies>
- <dependency>
  <groupId>org.apache.maven</groupId> 
  <artifactId>maven-plugin-api</artifactId> 
  <type>jar</type> 
  <version>2.0</version> 
  </dependency>
  </dependencies>
  </plugin>

 

 

描述文件中显示有可运行的目标touch,且输入参数值为maven的project.build.directory 参数。

运行插件的touch目标 mvn org.sonatype.plugins:first-maven-plugin:touch 结果可以验证touch创建文件是否成功。

 

3)插件前缀

运行插件时需要带上插件的goupId,artifactId,version,目标,参数,尤其groupId和aritifaceId比较长,mavne提供了缩写方式,即可以自定义插件前缀。

如果未使用其他仓库,可以在本地Maven仓库径org/apache/maven/plugins/maven-metadata-central.xml文件中看到插件组org.apache.maven.plugins的Maven元数据

 

<?xml version="1.0" encoding="UTF-8"?>
<metadata>
<plugins>
<plugin>
<name>Maven Clean Plugin</name>
<prefix>clean</prefix>
<artifactId>maven-clean-plugin</artifactId>
</plugin>
<plugin>
<name>Maven Compiler Plugin</name>
<prefix>compiler</prefix>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
<plugin>
<name>Maven Surefire Plugin</name>
<prefix>surefire</prefix>
<artifactId>maven-surefire-plugin</artifactId>
</plugin>
...
</plugins>
</metadata>

 

 如果使用了其他仓库,比如setting.xml中配置了

<pluginGroups>

 <pluginGroup>com.xxx.org.apache.maven.plugins</pluginGroup>

<pluginGroup>com.my.maven.plugins</pluginGroup>

</pluginGroups>

那么可以在本地仓库com\my\maven\plugins\maven-metadata-central.xml中查看插件组的元数据.

 

如果想要通过first:touch命令就能运行first-maven-plugin的touch目标,如所示,添加org.sonatype.plugins groupId至你的~/.m2/settings.xml文件中。这会让Maven优先扫描org.sonatype.plugins插件组

 

<settings>
...
<pluginGroups>
<pluginGroup>org.sonatype.plugins</pluginGroupd>
</pluginGroups>
</settings>
 这样子行得通是因为我们遵循了Maven插件的命名约定。如果你的插件有一个artifactId,并且它遵循模式maven-first-plugin,或者first-maven-plugin。Maven就会自动为你的插件赋予前缀first。换句话说,当Maven Plugin插件为你的插件生成插件描述符的时候,你不需要显式的为你的项目设定goalPrefix,###artifactId########,##plugin:descriptor目标会从你插件的artifactId中抽取前缀。${prefix}-maven-plugin, 或 maven-${prefix}-plugin,如果要显示配置插件,在插件pom.xml中配置
<build>
<plugins>
<plugin>
<artifactId>maven-plugin-plugin</artifactId>
<version>2.3</version>
<configuration>
<goalPrefix>blah</goalPrefix>
</configuration>
</plugin>
</plugins>
</build>
 

如果在~/.m2/settings.xml中的pluginGroups下添加了org.sonatype.plugins元素,你就应该能够在任何目录通过mvn blah:touch命令运行MyMojo

 

4)插件类注解

注解列表,可以用到Mojo类上

@goal <goalName> 这是唯一必需的注解,它给予目标一个在插件中唯一的名称 @requiresDependencyResolution <requireScope> 标记该mojo在可以运行之前,需要特定范围或者一个暗指的范围)的依赖。支持的范围有compile,runtime,和test。如果该注解有一个值为test,那么就是告诉Maven,除非测试范围的所有依赖都被正确解析了,否则该mojo不能运行。
@requiresProject (true|false) 标记该mojo必须在一个项目中运行,默认为true。这一点插件类型和骨架类型(archetype)相反,后者默认为false。 @requiresReports (true|false) 如果你正创建一个依赖于报告的项目,你就需要将requiresReports设置成true。该注解默认的值是false。
@aggregator (true|false) 一个aggregator设置成true的Mojo在Maven运行的时候只会被执行一次,例如,创建一个插件用来汇总一次构建包含的所有项目的报告。aggregator设置成true的目标只针对Maven构建的顶层项目运行。该注解默认的值是false @requiresOnline (true|false) 当该注解的值是true的时候,Maven在脱机模式运行的时候该目标运行就败。Maven会抛出一个错误。默认值:false。
@requiresDirectInvocation 当设置成true的时候,只有当用户显式的从命令行触发的时候,该插件才能得以执行。如果有人试图将其绑定到一个生命周期阶段,Maven就会抛出一个错默认值是false @phase <phaseName> 该注解指定目标默认的生命周期阶段。如果你将该目标的执行配置到了pom.xml而且没有指定一个阶段。Maven就会使用该注解的值将其绑定到一个默认的阶段
@execute [goal=goalName|phase=phaseName [lifecycle=lifecycleId]]

该注解有很多种使用方式。

@execute goal="<goal>" 会在执行当前目标之前运行声明的目标。目标名称使用prefix:goal标记指定。

@execute phase="<phase>"在执行当前生命周期之前,fork出另一个构建生命周期(直到指定的阶段)。如果没有指定生命周期,Maven会使用当前构建的生命周期

@execute lifecycle="<lifecycle>" phase="<phase>"会执行给定的生命周期。自定义的生命周期可以在META-INF/maven/lifecycle.xml中定义。

@execute phase="package" lifecycle="zip" @execute phase="compile" @execute goal="zip:zip"    

到Maven并没有使用Java 5的标准注解。而是使用了Commons Attributes6。在注解成为Java语言的一部分之前,CommonsAttributes为Java程序员提供了一种使用注解的方式。因为Maven必须支持Java比较老的版本,所以它不能使用任何Java 5的新特性。

 

4)mojo执行失败

当mojo的execute方法失败时,Mojo中的execute()方法抛出两个异会抛出两钟异常:

ojoExecutionException:一个MojoExecutionException应该是一个致命的异常,发生了一些不可恢复的错误。如果有什么事情导致构建完全终止,你就需要抛出一个MojoExecutionException;比如说你正试图往磁盘写数据,但没有可用空间。你希望停止构建并让用户看到“BUILD ERROR”信息。

 

MojoFailureException:相对没有那么严重。一个单元测试可以失败,或者MD5校验和可以失败;两者都是潜在的问题,但是你不会想要抛出一个异常去终止整个构建,当Maven遇到项目失败的时候,他会提供不同的“弹性”设置:

mvn -ff

最快失败模式:Maven会在遇到第一个失败的时候失败(停止)。

mvn -fae

最后失败模式:Maven会在构建最后失败(停止)。如果Maven refactor中一个

失败了,Maven会继续构建其它项目,并在构建最后报告失败。

mvn -fn

从不失败模式:Maven从来不会为一个失败停止,也不会报告失败。

 

5)Mojo参数
在mojo中可以使用注解来绑定参数,如

/**
* Any Object to print out.
* @parameter
* expression="${echo.message}"
* default-value="Hello Maven World"
*/
private Object message;

 参数message 绑定表达式为echo.message,如果mvn命令中传入 -Decho.message=aaa,那么aaa值将会赋给message参数。默认参数值取的是"Hello Maven World",默认参数值也可以取maven自带参数表达式。将值传给参数的方法,除了命令行之外,还可以在pom.xml或setting.xml中自定义,如:

<properties>
<echo.message>Hello Everybody</echo.message>
</properties>

 

还可以在pom的plugin中加入,如:

 

<build>
<plugins>
<plugin>
<groupId>org.sonatype.mavenbook.plugins</groupId>
<artifactId>first-maven-plugin</artifactId>
<version>1.0-SNAPSHOT</version>
<configuration>
<message>Hello Everybody!</message>
</configuration>
</plugin>
</plugins>
</build>

 如果我们想要在一个生命周期的不同阶段中运行EchoMojo两次,并且希望每次运行都能自定义message参数,我们可以在如下在POM中的execution级别配置这个参数值:

<build>
<plugins>
<plugin>
<groupId>org.sonatype.plugins</groupId>
<artifactId>first-maven-plugin</artifactId>
<version>1.0-SNAPSHOT</version>
<executions>
<execution>
<id>first-execution</id>
<phase>generate-resources</phase>
<goals>
<goal>echo</goal>
</goals>
<configuration>
<message>The Eagle has Landed!</message>
</configuration>
</execution>
<execution>
<id>second-execution</id>
<phase>validate</phase>
<goals>
<goal>echo</goal>
</goals>
<configuration>
<message>0.6-SNAPSHOT</message>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

 要配置一个多值的Mojo参数,你应该为这类参数使用一组元素。如果这个多值参数的名称是includes,你就可以使用一个includes元素,它包含一组include子元素。如果这个多值参数的名称是excludes,你就应该使用带有exclude子元素的excludes元素。要配置ZipMojo使其忽略所有以.txt及波浪号结尾的文件,你可以使用如下的插件配置。如:

<build>
<plugins>
<plugin>
<groupId>org.sonatype.plugins</groupId>
<artifactId>zip-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>**/*.txt</exclude>
<exclude>**/*~</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>

 其中zip插件的源码为:

/**
* Zips up the output directory.
* @goal zip
* @phase package
*/
public class ZipMojo extends AbstractMojo
{
/**
* The Zip archiver.
* @parameter expression="${component.org.codehaus.plexus.archiver.Archiver#zip}"
*/
private ZipArchiver zipArchiver;
/**
* Directory containing the build files.
* @parameter expression="/usr/local/hudson/hudson-home/jobs/maven-guide-zh-to-production/*/
private File buildDirectory;
/**
* Base directory of the project.
* @parameter expression="/usr/local/hudson/hudson-home/jobs/maven-guide-zh-to-production/*/
private File baseDirectory;
/**
* A set of file patterns to include in the zip.
* @parameter alias="includes"
*/
private String[] mIncludes;
/**
* A set of file patterns to exclude from the zip.
* @parameter alias="excludes"
*/
private String[] mExcludes;
public void setExcludes( String[] excludes ) { mExcludes = excludes; }
public void setIncludes( String[] includes ) { mIncludes = includes; }
public void execute()
throws MojoExecutionException
{
try {
zipArchiver.addDirectory( buildDirectory, includes, excludes );
zipArchiver.setDestFile( new File( baseDirectory, "output.zip" ) );
zipArchiver.createArchive();
} catch( Exception e ) {
throw new MojoExecutionException( "Could not zip", e );
}
}
}

 

6)依赖于一个Plexus组件

一个Mojo是一个由名为Plexus的Ioc容器管理的组件。Mojo可以通过使用@parameter#@component注解声明Mojo参数,然后依赖于其它Plexu管理的组件,ZipMojo使用@parameter注解依赖于一个Plexus组件,该依赖也可以使用@component注解来声明。如

/**
* The Zip archiver.
* @component role="org.codehaus.plexus.archiver.Archiver" roleHint="zip"
*/
private ZipArchiver zipArchiver;

 

当Maven初始化该Mojo的时候,它会尝试通过指定的role和role hint来获取Plexus组件。在该例中,这个Mojo关联到一个ZipArchiver组件,后者能帮助ZipMojo创建ZIP文件。

 

maven的plugin插件有个descriptor目标绑定到了generate-resources阶段,该目标根据Mojo的注解生成插件描述符。有下列注解可以用在参数上,虽然也可以在公有setter方法上使用这些注解,不过一般是使用在私有变量上:

@parameter [alias="someAlias"] [expression="${someExpression}"] [defaultvalue="value"]

@required

@readonly:如果使用该注解,用户就不能从POM直接配置这个参数

@component:告诉Maven使用Plexus组件填充该字段。一个正确的@component注解值如下:  @component role="org.codehaus.plexus.archiver.Archiver" roleHint="zip"

也可以使用@parameter expression="${component.org.codehaus.plexus.archiver.Archiver#zip}"

@deprecated:该参数以过期,不再推荐使用。

 

 7)创建自定义的生命周期

自定义生命周期必须在插件项目的META-INF/maven/lifecycle.xml文件中定义。你可以引入这个定义在src/main/resources下的META-INF/maven/lifecycle.xml文件

结合例子看下:项目目录结构如下

 

 

package org.mtp.plugins;

import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;

/**
 * 使用execute注解使用touch生命周期的goal
 * @goal after-touch
 * @execute lifecycle="touchcycle" phase="package"
 */
public class MyAfterLifeCycleMojo  extends AbstractMojo{

	@Override
	public void execute() throws MojoExecutionException, MojoFailureException {
		getLog().info("begin MyAfterLifeCycleMojo.");
		
		getLog().info("end MyAfterLifeCycleMojo.");
		
	}

}

package org.mtp.plugins;

import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
/**
 * 在 after-touch 目标之后执行此mojo
 * @goal after-cycle
 * @execute goal="after-touch"
 */
public class MyAfterMojo extends AbstractMojo{

	@Override
	public void execute() throws MojoExecutionException, MojoFailureException {
		getLog().info("begin MyAfterMojo.");
		
		getLog().info("end MyAfterMojo.");
		
	}

}

package org.mtp.plugins;

import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
/**
 * 在生命周期阶段compiles之后执行
 * @goal after-phase-resouces
 * @execute phase="compile"
 */
public class MyAfterPhaseMojo extends AbstractMojo{

	@Override
	public void execute() throws MojoExecutionException, MojoFailureException {
		getLog().info("begin MyAfterPhaseMojo.");
		
		getLog().info("end MyAfterPhaseMojo.");
		
	}

}
//MyMojo在上文中已经列出
 lifecycle.xml内容为:

 

 

<lifecycles>
	<lifecycle>
		<id>touchcycle</id>
		<phases>
			<phase>
				<id>package</id>
				<executions>
					<execution>
						<goals>
							<goal>touch</goal>
						</goals>
					</execution>
				</executions>
			</phase>
		</phases>
	</lifecycle>
</lifecycles>
 

 

 mvn install之后,可以分别运行几个goal看看效果

mvn blabla:after-cycle 会触发after-touch goal,after-touch会触发touchcycle的package,它会触发touch目标,所以执行的Mojo依次是MyMojo,MyAfterLifeCycleMojo,MyAfterMojo

mvn blabla:after-phase-resouces 会先触发compile阶段之前所有绑定的插件,所以触发结果为:

  

[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: 'blabla'.
[INFO] ------------------------------------------------------------------------
[INFO] Building first-maven-plugin Maven Mojo
[INFO]    task-segment: [blabla:after-phase-resouces]
[INFO] ------------------------------------------------------------------------
[INFO] Preparing blabla:after-phase-resouces
[INFO] [plugin:descriptor {execution: default-descriptor}]
[WARNING] Goal prefix is: blabla; Maven currently expects it to be first
[INFO] Using 2 extractors.
[INFO] Applying extractor for language: java
[INFO] Extractor for language: java found 4 mojo descriptors.
[INFO] Applying extractor for language: bsh
[INFO] Extractor for language: bsh found 0 mojo descriptors.
[INFO] [resources:resources {execution: default-resources}]
[WARNING] Using platform encoding (GBK actually) to copy filtered resources, i.e
. build is platform dependent!
[INFO] Copying 1 resource
[INFO] [compiler:compile {execution: default-compile}]
[INFO] Nothing to compile - all classes are up to date
[INFO] [blabla:after-phase-resouces {execution: default-cli}]
[INFO] begin MyAfterPhaseMojo.
[INFO] end MyAfterPhaseMojo.
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL

 

 

  • 大小: 15.5 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics