Maven和Maven插件
程序员文章站
2024-03-20 20:31:10
...
[b]人生是一张茶几,上面摆满了杯具,请让我们的杯具与众不同。[/b]
这是我这篇博文的一个主题。
我们知道maven是一个项目管理的工具,他把项目抽象为一个个的生命周期和阶段。我们先来介绍一下maven最重要的几个概念:
[list]
1、lifecycle 生命周期,一个项目在maven中有三个生命周期,分别为default,clean,site。default主要是编译和部署生命周期,clean是清理生命周期,site是生成报表、工程文档等生命周期。
2、phase 生命周期中阶段。如default的生命周期中拥有validate、initialize、compile、test-compile、prepare-package、package、install、deploy等等的阶段。阶段是顺序执行的。
3、goal 阶段中的目标。每一个阶段中,蕴含着一个或多个目标。
4、mojo 执行目标的具体代类
[/list]
形象的来一个比喻,如同下面一张图所示:
[img]http://dl.iteye.com/upload/attachment/286102/dc8a2290-18ab-37c5-8049-89673d011b8d.jpg[/img]
一个项目的生命周期如同一个人的生命周期(lifecycle),分为多个阶段(phase),如3岁前是幼儿期,4-22岁是幼年期,23-53是中轻年期,51-70是老年期。而每个阶段(phase)我们又会有不一样的目标(goal),比如幼儿期,我们的目标(goal)是喝奶,幼年期的目标(goal)是读书、长大,中年期的目标是结婚生子等等等等。这些组成我们人生的杯具。但是我们作为一个杯具的执行者(mojo),还得一步一步的去走我们的各个阶段,实现我们的各个目标。
项目都有标准的生命周期,编译前检查、资源生成、编译、部署、发布等等。但是每个项目又是如此不同,我们怎样改变我们的项目,使得这一个个的杯具有所不同呢?我们可以使用maven的插件和编写maven的插件来实现。比如我们想在编译前,去读取一台网络设备的配置;再或则需要收集其他资源等等。maven插件让我们项目丰富多彩,跟我们人生的杯具一样,请让我们的杯具与众不同。
讲解了maven的一些概念以后,我们进入maven插件的编写讲述上。
maven插件,也是以mojo来体现的,写插件就是写mojo。那为什么maven的标准mojo成为标准的生命周期中的goal实现,而我们的插件就跟二奶一样,不被承认,只能叫做插件呢。
比如我们在运行:maven install的时候,到底运行了什么?我们让maven执行默认生命周期中的一个阶段(phase),这个阶段叫install,而这个阶段默认绑定了一个目标(goal),目标的名称也叫install。也就是说我们让maven唤醒项目的一次install目标。如执行maven install:install。maven会根据默认的生命周期阶段,先执行先前的阶段(validate,initialize...),然后执行编译和安装。插件的运行方式类似,如maven eclipse:eclipse 我们让maven唤起运行eclipse的插件,生成eclipse的项目文件。他们运行方式如此的相似,是因为他们本来就是同样的东西--mojo。
插件跟标准流程如同二奶跟合法妻子一样。
1、他们都是不被承认的
2、他们的存在都是为了解决需求
3、他们都是女人
[img]http://dl.iteye.com/upload/attachment/286118/8c588c40-2736-3678-b092-b378050174f6.jpg[/img]
1、插件也是不被maven承认的
2、它们都是为了解决项目的需求
3、它们都是mojo
了解了我们的maven部分概念和插件的定位之后,我们来写我们的第一个maven插件。插件之hello world。
所有的mojo都应该继承自org.apache.maven.plugin.AbstractMojo,我们来建立我们的maven插件工程。
跟普通Maven的项目一样,自己定义groupId和artifactId。我们这里分别定义groupId为com.alibaba.maven.plugins和greeting-maven-plugin。
archetypeGroupId和archetypeArtifactId用来定位用哪个maven的工程模板来建立项目。当然我们使用的是maven-archetype-mojo模板来建立插件项目。
Ok,如上所示我们复写了execute方法,最重要@goal的一个annotation,它定义了这个mojo跟goal一一对应的关系。现在我们运行命令mvn install 把该插件先发布到本地库。之后我们便可以执行我们的插件了。
插件的运行方式为:mvn groupID:artifactID:version:goal
按照我们的项目,那么我们运行插件应该:mvn com.alibaba.maven.plugins:greeting-maven-plugin:1.0-SNAPSHOT:sayHello
看看,我们是不是已经在控制台看到我们打出的"Hello World"文字了。想想,为什么mvn eclipse:eclipse的插件运行方式可以这么简单。
[img]http://dl.iteye.com/upload/attachment/286130/6734e549-e549-3622-b378-b1d12f3f85ae.jpg[/img]
怎么减少输入呢?
首先,我们在maven的setting.xml配置文件中,可以找到这样一个配置项:
如果这里配置上我们的groupID,如我们的com.alibaba.maven.plugins,那么groupId的输入便可省略了。
另外,我们的项目名称DartifactId如果以${name}-maven-plugin或以maven-${name}-plugin的格式命名,我们便能省去-maven-plugin等信息。
version本来可以省略,maven会找到最新的版本来执行。
那么省略后的执行命令就可以这样写了:mvn greeting:sayHello
Ok,那么我要运行插件时输入参数,该怎么处理呢?如同 mvn install -Dmaven.test.skip=true。我们重写我们的mojo,加入@parameter的annotation。如下
在install一把,然后运行
看看是否已经ok了。
上面的插件都在命令行模式下运行,下面我再把项目中运行的插件方式和方法做一个简要的梳理。这些类似的插件有很多,比如jetty插件,各种reporting插件等等。
我们先创建一个测试工程,用于应用和测试我们写的HelloWrold插件。
然后在pom文件中加入插件的依赖,如下
对该项目进行编译,mvn install 后,我们会发现在项目的initialize阶段,便会打印出hello world!的信息。插件绑定到了特定的phase,如果我们不通过编译该测试工程运行插件,我们依然通过命令行,比如 mvn greeting:sayHello,我们会发现,在绑定phase阶段的先前阶段会先顺序执行后,才开始运行插件。
插件配置中也可以配置参数,优先级以配置项为先,而命令行参数为后。如我们可以这样配置插件参数:
讲完了插件以后,一些分享没有涉及的知识点可以去参考maven的官方文档。比如annotation中没有涉及的一些点。可参考http://maven.apache.org/developers/mojo-api-specification.html
最后本想把一些插件的源码拿出来解析一把,以后有时间再写吧。或许读者们可以把这个事情当做自己的提高手段。
这是我这篇博文的一个主题。
我们知道maven是一个项目管理的工具,他把项目抽象为一个个的生命周期和阶段。我们先来介绍一下maven最重要的几个概念:
[list]
1、lifecycle 生命周期,一个项目在maven中有三个生命周期,分别为default,clean,site。default主要是编译和部署生命周期,clean是清理生命周期,site是生成报表、工程文档等生命周期。
2、phase 生命周期中阶段。如default的生命周期中拥有validate、initialize、compile、test-compile、prepare-package、package、install、deploy等等的阶段。阶段是顺序执行的。
3、goal 阶段中的目标。每一个阶段中,蕴含着一个或多个目标。
4、mojo 执行目标的具体代类
[/list]
形象的来一个比喻,如同下面一张图所示:
[img]http://dl.iteye.com/upload/attachment/286102/dc8a2290-18ab-37c5-8049-89673d011b8d.jpg[/img]
一个项目的生命周期如同一个人的生命周期(lifecycle),分为多个阶段(phase),如3岁前是幼儿期,4-22岁是幼年期,23-53是中轻年期,51-70是老年期。而每个阶段(phase)我们又会有不一样的目标(goal),比如幼儿期,我们的目标(goal)是喝奶,幼年期的目标(goal)是读书、长大,中年期的目标是结婚生子等等等等。这些组成我们人生的杯具。但是我们作为一个杯具的执行者(mojo),还得一步一步的去走我们的各个阶段,实现我们的各个目标。
项目都有标准的生命周期,编译前检查、资源生成、编译、部署、发布等等。但是每个项目又是如此不同,我们怎样改变我们的项目,使得这一个个的杯具有所不同呢?我们可以使用maven的插件和编写maven的插件来实现。比如我们想在编译前,去读取一台网络设备的配置;再或则需要收集其他资源等等。maven插件让我们项目丰富多彩,跟我们人生的杯具一样,请让我们的杯具与众不同。
讲解了maven的一些概念以后,我们进入maven插件的编写讲述上。
maven插件,也是以mojo来体现的,写插件就是写mojo。那为什么maven的标准mojo成为标准的生命周期中的goal实现,而我们的插件就跟二奶一样,不被承认,只能叫做插件呢。
比如我们在运行:maven install的时候,到底运行了什么?我们让maven执行默认生命周期中的一个阶段(phase),这个阶段叫install,而这个阶段默认绑定了一个目标(goal),目标的名称也叫install。也就是说我们让maven唤醒项目的一次install目标。如执行maven install:install。maven会根据默认的生命周期阶段,先执行先前的阶段(validate,initialize...),然后执行编译和安装。插件的运行方式类似,如maven eclipse:eclipse 我们让maven唤起运行eclipse的插件,生成eclipse的项目文件。他们运行方式如此的相似,是因为他们本来就是同样的东西--mojo。
插件跟标准流程如同二奶跟合法妻子一样。
1、他们都是不被承认的
2、他们的存在都是为了解决需求
3、他们都是女人
[img]http://dl.iteye.com/upload/attachment/286118/8c588c40-2736-3678-b092-b378050174f6.jpg[/img]
1、插件也是不被maven承认的
2、它们都是为了解决项目的需求
3、它们都是mojo
了解了我们的maven部分概念和插件的定位之后,我们来写我们的第一个maven插件。插件之hello world。
所有的mojo都应该继承自org.apache.maven.plugin.AbstractMojo,我们来建立我们的maven插件工程。
mvn archetype:create -DgroupId=com.alibaba.maven.plugins -DartifactId=greeting-maven-plugin -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-mojo
跟普通Maven的项目一样,自己定义groupId和artifactId。我们这里分别定义groupId为com.alibaba.maven.plugins和greeting-maven-plugin。
archetypeGroupId和archetypeArtifactId用来定位用哪个maven的工程模板来建立项目。当然我们使用的是maven-archetype-mojo模板来建立插件项目。
/** @author xingming.zhaoxm
* @goal sayHello
*/
public class HelloWorldMojo extends AbstractMojo{
@Override
public void execute() throws MojoExecutionException, MojoFailureException {
getLog().info("Hello World!");
}}
Ok,如上所示我们复写了execute方法,最重要@goal的一个annotation,它定义了这个mojo跟goal一一对应的关系。现在我们运行命令mvn install 把该插件先发布到本地库。之后我们便可以执行我们的插件了。
插件的运行方式为:mvn groupID:artifactID:version:goal
按照我们的项目,那么我们运行插件应该:mvn com.alibaba.maven.plugins:greeting-maven-plugin:1.0-SNAPSHOT:sayHello
看看,我们是不是已经在控制台看到我们打出的"Hello World"文字了。想想,为什么mvn eclipse:eclipse的插件运行方式可以这么简单。
[img]http://dl.iteye.com/upload/attachment/286130/6734e549-e549-3622-b378-b1d12f3f85ae.jpg[/img]
怎么减少输入呢?
首先,我们在maven的setting.xml配置文件中,可以找到这样一个配置项:
<pluginGroups>
<pluginGroup>*</pluginGroup>
</pluginGroups>
如果这里配置上我们的groupID,如我们的com.alibaba.maven.plugins,那么groupId的输入便可省略了。
另外,我们的项目名称DartifactId如果以${name}-maven-plugin或以maven-${name}-plugin的格式命名,我们便能省去-maven-plugin等信息。
version本来可以省略,maven会找到最新的版本来执行。
那么省略后的执行命令就可以这样写了:mvn greeting:sayHello
Ok,那么我要运行插件时输入参数,该怎么处理呢?如同 mvn install -Dmaven.test.skip=true。我们重写我们的mojo,加入@parameter的annotation。如下
/**
* @author xingming.zhaoxm
* @goal sayHello
*/
public class HelloWorldMojo extends AbstractMojo{
/**
* @parameter default-value="Somebody" expression="${username}
*/
private String userName;
@Override
public void execute() throws MojoExecutionException, MojoFailureException {
getLog().info("Hello World!"+userName);
}}
在install一把,然后运行
mvn greeting:sayHello -Dusername=白痴
看看是否已经ok了。
上面的插件都在命令行模式下运行,下面我再把项目中运行的插件方式和方法做一个简要的梳理。这些类似的插件有很多,比如jetty插件,各种reporting插件等等。
我们先创建一个测试工程,用于应用和测试我们写的HelloWrold插件。
mvn archetype:create -DgroupId=com.alibaba -DartifactId=test
然后在pom文件中加入插件的依赖,如下
<build>
<plugins>
<plugin>
<groupId>com.alibaba.maven.plugins</groupId>
<artifactId>greeting-maven-plugin</artifactId>
<version>1.0-SNAPSHOT</version>
<executions>
<execution>
<phase>initialize</phase>
<goals>
<goal>sayHello</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
对该项目进行编译,mvn install 后,我们会发现在项目的initialize阶段,便会打印出hello world!的信息。插件绑定到了特定的phase,如果我们不通过编译该测试工程运行插件,我们依然通过命令行,比如 mvn greeting:sayHello,我们会发现,在绑定phase阶段的先前阶段会先顺序执行后,才开始运行插件。
插件配置中也可以配置参数,优先级以配置项为先,而命令行参数为后。如我们可以这样配置插件参数:
<build>
<plugins>
<plugin>
<groupId>com.alibaba.maven.plugins</groupId>
<artifactId>greeting-maven-plugin</artifactId>
<version>1.0-SNAPSHOT</version>
<configuration>
<userName>阿娇</userName>
</configuration>
<executions>
<execution>
<phase>initialize</phase>
<goals>
<goal>sayHello</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
讲完了插件以后,一些分享没有涉及的知识点可以去参考maven的官方文档。比如annotation中没有涉及的一些点。可参考http://maven.apache.org/developers/mojo-api-specification.html
最后本想把一些插件的源码拿出来解析一把,以后有时间再写吧。或许读者们可以把这个事情当做自己的提高手段。
上一篇: 前后端分离时导入excel
下一篇: jquery 判断图片是否存在