在Maven2强大功能的魅力诱惑下,很多公司渐渐开始从Ant转向了Maven2,而且由于Maven2本来就支持运行Ant脚本,这样就大大降低了开发团队在从Ant向Maven2过渡所需难度。
相对于Ant对开发人员的相对开放的姿态,Maven2对开发人员来说看起来比较透明。很多对以前老的Ant程序员来说需要编写target的问题在Maven2中都变成了一些简单的配置。理论上讲,这样一来,Maven2的使用起点应该是比Ant低多了,因为在Ant中程序员至少应该熟悉Velocity语法才行。但是由于Maven2到目前为止还没有成套系统的中文资料或文档可供查看,使得Maven2的使用看起来并不比Ant简单多少。反倒是由于什么东西都需要进行配置,但手头又没有相关的说明文档,是很多开发人员在刚开始使用Maven2时有些无从下手的感觉。更让人痛苦的是网上很多关于Maven的资料都是针对1.0版本的,更可恨的是很多资料明明是基于1.0版本写的,可是我们的作者只是换换标题和其中的几个关键字信息就堂而皇之的将其作为2.0的资料贴在自己的博客中(极其不负责任)。
前面这一段是废话,仅仅是为了将大家引入我下面的话题,在使用Maven进行工程管理的过程中,我们可能希望将现有的Ant脚本集成到我们的POM中,我们甚至希望在POM中不出现Ant脚本的情况下将以前已经写好并使用了很长一段时间的工程脚本集成到我们现有的Maven工程当中。同时,或者现有的Maven无法支持我们需要完成的一些特殊任务。
这样一个话题自然就摆在了我们的面前,那就是Maven2的插件开发。
说道Maven2就不得不说说Maven2主要部分的标准路径结构(如下图)。
xml 代码
<sourceDirectory>src/main/java</sourceDirectory>
<scriptSourceDirectory>src/main/scripts</scriptSourceDirectory>
<testSourceDirectory>src/test/java</testSurceDirectory>
<outputDirectory>target/classes</outputDirectory>
<testOutputDirectory>target/test-classes</testOutputDirectory>
这些路径是Maven2配置的基础(还有些其他路径,不再详述),
通常情况下,我们没必要显式声明路径结构。除非我们要改变其标准路径结构时,可以通过配置以上参数来进行个性化配置。但是Maven2的官方网站强烈建议使用Maven的标准路径。而且Maven官方提供的某些插件也只仅仅支持到了标准路径,对于非标准路径这些配置不起任何作用(如Cobertura1.8的plug-in)。
(Maven2官方提供的Cobertura1.8的plug-in有些Bug,无法正确生成最后的Coverage Test Reporting。关于这个问题的解决我打算重开一个专题,以便今后查阅。)
因此,我在本篇文章中介绍的插件开发也采用Maven2的标准路径。先说说Ant plug-in的开发,然后在介绍用Java进行plug-in 开发。
Ant
的
Maven2 plug-in
开发
Maven的一个很明显有别与Ant的优势就是在于明确了工程中所用资源包的版本信息,目前我们在工程开发过程中都不免需要用到大量的免费开源的第三方插件,而这些插件在升级过程中的向前兼容做的有时候确实不太理想,就想Hibernate在升级到3.0后包结构的变化一样,让很多开发人员在刚开始使用时都是一头雾水,但是由于Maven2可以明确指明所使用的资源包版本信息,这样就避免了工程中由于资源包版本混乱导致程序崩溃的问题。
Ant脚本的plug-in开发需要在POM中声明两个资源包,一个是在编译打包生成plug-in的jar文件时所需要用到的资源包,一个是在plug-in在被执行时,运行Ant脚本所需要的资源包。具体POM的配置如下所示:
xml 代码
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>org.myproject.plugins</groupId>
<artifactId>hello-plugin</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>maven-plugin</packaging>
<name>Hello Plugin</name>
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-script-ant</artifactId>
<version>2.0.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-plugin-plugin</artifactId>
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-tools-ant</artifactId>
<version>2.0.1</version>
</dependency>
</dependencies>
<configuration>
<goalPrefix>hello</goalPrefix>
</configuration>
</plugin>
</plugins>
</build>
</project>
可以看出我这里并没有对Maven2的路径做任何显示的声明。根据Maven2的标准路径,我们需要将plug-in工程中的脚本文件放在src/main/scripts路径下去。所以,首先在工程中建立这样一个目录,然后在目录中开始编写Ant脚本(hello.build.xml):
xml 代码
<project>
<target name="hello">
<echo>ANT SCRIPT ECHOS:Hello, World</echo>
</target>
</project>
接下来编写MOJO脚本(hello.mojos.xml),MOJO是Ant脚本执行的关键,我们也需要将其与Ant脚本放置在同一个目录src/main/scripts下,在该文件中定义Maven2的goal和需要执行的Ant脚本中target名称。具体内容如下:
xml 代码
<pluginMetadata>
<mojos>
<mojo>
<goal>hello</goal>
<call>hello</call>
<description>Say Hello, World.</description>
</mojo>
</mojos>
</pluginMetadata>
至此,一个完整的基于Maven2的Ant plug-in就已经开发完毕。为了方便举例,我在这里的Ant脚本写得相当简单,你可以在这里根据你的工程具体需求尽情发挥。
接下来执行一下“mvn install”,提示内容如下则说明已经成功发布到了本地仓库中:
D:\eclipse\workspace\hello-plugin>mvn install -e -o
+ Error stacktraces are turned on.
[INFO]
NOTE: Maven is executing in offline mode. Any artifacts not already in your local
repository will be inaccessible.
[INFO] Scanning for projects...
[INFO] ----------------------------------------------------------------------------
[INFO] Building Hello Plugin
[INFO] task-segment: [install]
[INFO] ----------------------------------------------------------------------------
[INFO] [plugin:descriptor]
[WARNING] Goal prefix is: hello; Maven currently expects it to be hello
[INFO] Using 3 extractors.
[INFO] Applying extractor for language: java
[INFO] Extractor for language: java found 1 mojo descriptors.
[INFO] Applying extractor for language: bsh
[INFO] Extractor for language: bsh found 0 mojo descriptors.
[INFO] Applying extractor for language: ant
[INFO] Extractor for language: ant found 1 mojo descriptors.
[INFO] [resources:resources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [compiler:compile]
[INFO] Nothing to compile - all classes are up to date
[INFO] [resources:testResources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [compiler:testCompile]
[INFO] No sources to compile
[INFO] [surefire:test]
[INFO] No tests to run.
[INFO] [jar:jar]
[INFO] Building jar: D:\eclipse\workspace\hello-plugin\target\hello-plugin-1.0-S
NAPSHOT.jar
[INFO] [plugin:addPluginArtifactMetadata]
[INFO] [install:install]
[INFO] Installing D:\eclipse\workspace\hello-plugin\target\hello-plugin-1.0-SNAP
SHOT.jar to E:\maven-2.0.4\.m2\repository\org\myproject\plugins\hello-plugin\1.0
-SNAPSHOT\hello-plugin-1.0-SNAPSHOT.jar
[INFO] [plugin:updateRegistry]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3 seconds
[INFO] Finished at: Thu Jun 28 10:39:02 CST 2007
[INFO] Final Memory: 9M/17M
[INFO] ------------------------------------------------------------------------
D:\eclipse\workspace\hello-plugin>
接下来就可以在你的工程中将该插件集成上去了,具体做法为将如下代码加入你工程的POM中:
xml 代码
<build>
<plugins>
<plugin>
<groupId>org.myproject.plugins</groupId>
<artifactId>hello-plugin</artifactId>
<version>1.0-SNAPSHOT</version>
</plugin>
</plugins>
</build>
当然,Maven2对于Ant脚本的支持也并不是仅仅只到了插件级,你还可以在POM中直接使用Ant脚本来完成一些任务。为了保证本篇文章的完整性,关于这个专题我打算再开一篇文章专门说明。
Java
的
Maven2 plug-in
开发
在已经建立的Ant plug-in工程中引入代码如下(对与Struts程序员来说,是不是有点似曾相识的感觉!):
java 代码
package org.danlley.com;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
/**
* Says "Hi" to the user.
* @goal sayhi
*/
public class GreetingMojo extends AbstractMojo
{
public void execute() throws MojoExecutionException
{
getLog().info("-------------------------------------------");
getLog().info("| Hello, world. |");
getLog().info("-------------------------------------------");
}
}
其中AbstractMojo和MojoExecutionException都是Maven2核心支持包中的类,你可以在Maven2安装路径的lib目录下找到maven-core-2.0.6-uber.jar(我用的是version2.0.6,不过现在我在官方网站看到2.0.7也已经出来了)
重新编译,重新install。然后新建工程,以便测试插件是否能够正常工作。
新工程的POM如下:
xml 代码
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.danlley.com</groupId>
<artifactId>mvnproj</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>mvnproj</name>
<url>http://maven.apache.org</url>
<build>
<plugins>
<plugin>
<groupId>org.myproject.plugins</groupId>
<artifactId>hello-plugin</artifactId>
<version>1.0-SNAPSHOT</version>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant</artifactId>
<version>1.7.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
执行命令,运行结果如下则说明插件开发成功!
E:\myproj\mvnproj>mvn package hello:hello hello:sayhi -e -o
+ Error stacktraces are turned on.
[INFO]NOTE: Maven is executing in offline mode. Any artifacts not already in your local
repository will be inaccessible.
[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: 'hello'.
[INFO] ----------------------------------------------------------------------------
[INFO] Building mvnproj
[INFO] task-segment: [package]
[INFO] ----------------------------------------------------------------------------
[INFO] [resources:resources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [compiler:compile]
[INFO] Nothing to compile - all classes are up to date
[INFO] [resources:testResources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [compiler:testCompile]
[INFO] Nothing to compile - all classes are up to date
[INFO] [surefire:test]
[INFO] Surefire report directory: E:\myproj\mvnproj\target\surefire-reports
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running org.danlley.com.AppTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.047 sec
Results :
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO] [jar:jar]
[INFO] Building jar: E:\myproj\mvnproj\target\mvnproj-1.0-SNAPSHOT.jar
[INFO] ----------------------------------------------------------------------------
[INFO] Building mvnproj
[INFO] task-segment: [hello:hello] (aggregator-style)
[INFO] ----------------------------------------------------------------------------
[INFO] [hello:hello]
hello:
[echo] ANT SCRIPT ECHOS:Hello, World
[INFO] ----------------------------------------------------------------------------
[INFO] Building mvnproj
[INFO] task-segment: [hello:sayhi]
[INFO] ----------------------------------------------------------------------------
[INFO] [hello:sayhi]
[INFO] -------------------------------------------
[INFO] | Hello, world. |
[INFO] -------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 4 seconds
[INFO] Finished at: Thu Jun 28 12:58:51 CST 2007
[INFO] Final Memory: 5M/10M
[INFO] ------------------------------------------------------------------------