Maven 插件編寫 之 Mojo

1.Maven

Maven 作為一個優(yōu)秀的項目管理工具,其插件機制為其功能擴展提供了非常大的便捷性。雖然說大多數(shù)情況下,我們可能不太會自己去編寫 Maven 插件,但不排除在某些特殊的情況下,我們需要去完成一個自己的插件,來協(xié)助我們處理某些比較通用的事情。

2.Maven 插件的命名規(guī)范

一般來說,我們會將自己的插件命名為<myplugin>-maven-plugin,而不推薦使用maven-<myplugin>-plugin,因為后者是 Maven 團隊維護官方插件的保留命名方式,使用這個命名方式會侵犯 Apache Maven 商標。

3.什么是 Mojo?

Mojo 就是Maven plain Old Java Object。每一個 Mojo 就是 Maven 中的一個執(zhí)行目標(executable goal),而插件則是對單個或多個相關(guān)的 Mojo 做統(tǒng)一分發(fā)。一個 Mojo 包含一個簡單的 Java 類。插件中多個類似 Mojo 的通用之處可以使用抽象父類來封裝。

4.創(chuàng)建 Mojo 工程

mojo項目

這里,我們使用 idea 作為開發(fā)工具進行講解,創(chuàng)建工程選擇 Maven,然后在模板中找到 maven-archetype-plugin,點擊下一步,輸入對應的參數(shù),如:io.fredia/test-maven-plugin/1.0-SNAPSHOT,最后點擊完成即可創(chuàng)建一個簡單的 Mojo 工程。

創(chuàng)建完成后,工程內(nèi)會生成對應的 pom.xml 文件。其內(nèi)容比較簡單,與普通 Maven 工程的 pom.xml 基本一致,只是自動添加了對 maven-plugin-api 的依賴,這個依賴里面會包含一些 Mojo 的接口與抽象類,在后續(xù)編寫具體的 Mojo 時再進行詳細講解。

<dependency>
  <groupId>org.apache.maven</groupId>
  <artifactId>maven-plugin-api</artifactId>
  <version>2.0</version>
</dependency>
<dependency>
   <groupId>org.apache.maven.plugin-tools</groupId>
   <artifactId>maven-plugin-annotations</artifactId>
   <version>3.2</version>
</dependency>

注意打包方式:

<packaging>maven-plugin</packaging>

5.Mojo 的創(chuàng)建

工程創(chuàng)建完畢后,創(chuàng)建一個簡單MoJo

package io.fredia.test;

/*
 * Copyright 2001-2005 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;

/**
 * Goal which touches a timestamp file.
 *
 * @deprecated Don't use!
 */
@Mojo(name = "hello", defaultPhase = LifecyclePhase.PROCESS_SOURCES)
public class MyMojo extends AbstractMojo {
    /**
     * Location of the file.
     */
    /*
     * @Parameter(defaultValue = "${project.build.directory}", property =
     * "outputDir", required = true) private File outputDirectory;
     */

    public void execute() throws MojoExecutionException, MojoFailureException {
        System.out.println("hello world");
    }
}

解釋一下這個類,我們發(fā)現(xiàn)它繼承了 AbstractMojo 這個抽象類,并實現(xiàn)了 execute() 方法,該方法就是用來定義這個 Mojo 具體操作內(nèi)容,我們只需要根據(jù)自己的需要來編寫自己的實現(xiàn)即可。

Mojo 操作的實現(xiàn)我們了解了,那怎么讓 Maven 知道這是一個 Mojo 而不是一個普通的 Java 類呢?這里,就需要說一下 Mojo 的查找機制了,在處理源碼的時候,plugin-tools 會把使用了 @Mojo 注解或 Javadoc 里包含 @goal 注釋的類來當作一個 Mojo 類。在上面的例子中,我們使用了 @MoJo 的方法來聲明一個 Mojo。同樣我們也可以使用 Javadoc 注解來進行聲明:

/**
 * @goal hello
 */
public class MyMojo extends AbstractMojo {

    public void execute() throws MojoExecutionException, MojoFailureException {
        System.out.println("hello fredia");
    }

}

6.如何運行自定義 Plugin

與使用其它插件類似,我們需要在 pom.xml 文件中引入插件:

<build>
    <plugins>
        <plugin>
            <groupId>io.fredia</groupId>
            <artifactId>test-maven-plugin</artifactId>
            <version>1.0-SNAPSHOT</version>
        </plugin>
    </plugins>
</build>

mvn命令行執(zhí)行如下:

mvn io.fredia:test-maven-plugin:1.0-SNAPSHOT:hello

即可看到輸出:

[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building test-maven-plugin Maven Mojo 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- test-maven-plugin:1.0-SNAPSHOT:hello (default-cli) @ test-maven-plugin ---
hello fredia
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.249 s
[INFO] Finished at: 2017-11-22T12:59:47+08:00
[INFO] Final Memory: 6M/123M
[INFO] ------------------------------------------------------------------------

7.縮短執(zhí)行命令

在剛才運行插件的時候,我們使用全量的插件指引,但這個實在是太長太繁瑣了,那我們是否可以縮短我們的執(zhí)行命令呢?答案肯定是可以的,如果你想要執(zhí)行的是你本地庫中最新版本的插件,那么你可以刪除掉版本號;如果你的命名滿足前面提及的兩種命令方式,你可以直接使用插件名及 goal 名來運行對應的插件,如:

mvn test:hello

結(jié)果一樣

8.綁定 Maven 執(zhí)行周期

你還可以將插件配置為將特定目標,從而附加到構(gòu)建生命周期中的某個特定階段。如:

<build>
    <plugins>
        <plugin>
            <groupId>io.fredia</groupId>
            <artifactId>test-maven-plugin</artifactId>
            <version>1.0-SNAPSHOT</version>
            <executions>
                <execution>
                    <goals>
                        <goal>hello</goal>
                    </goals>
                    <phase>package</phase>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

最后附加一個自己基于maven-plugin開發(fā)的代碼生成器,實現(xiàn)高度的代碼復用和全自動化

gitee地址:https://gitee.com/fredia/code-factory/ 望多多支持

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內(nèi)容