自定義 maven 插件


自定義maven插件

maven的價值除了它的版本管理,依賴管理,以及規范化java代碼結構之外,它豐富且易用的插件也是非常重要的特性.下面我們就來自定義一個maven插件.來進一步認識maven.

maven插件開發流程

  1. 創建maven插件項目
  2. 編寫maven目標(goal)
  3. 提供maven擴展配置點
  4. 實現目標行為
  5. 錯誤處理和日志
  6. 測試插件

實現

  • 創建maven插件項目

創建maven插件項目與普通的maven類似,只是使用的模板不同,這里使用官方的插件模板:

mvn archetype:generate

然后選擇:3: internal -> org.apache.maven.archetypes:maven-archetype-plugin (An archetype which contains a sample Maven plugin.)
項目層級結構:

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/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.ll</groupId>
  <artifactId>loc-maven-plugin</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>maven-plugin</packaging>

  <name>loc-maven-plugin Maven Plugin</name>

  <!-- FIXME change it to the project's website -->
  <url>http://maven.apache.org</url>

  <properties>
    <maven.compiler.source>8</maven.compiler.source>
    <maven.compiler.target>8</maven.compiler.target>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <dependency>
      <groupId>org.apache.maven</groupId>
      <artifactId>maven-plugin-api</artifactId>
      <version>3.0</version>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.8.2</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <build>
    <plugins>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-invoker-plugin</artifactId>
          <version>3.1.0</version>
          <configuration>
            <cloneProjectsTo>${project.build.directory}/it</cloneProjectsTo>
            <postBuildHookScript>verify</postBuildHookScript>
            <goals>
              <goal>install</goal>
            </goals>
          </configuration>
          <executions>
            <execution>
              <id>integration-test</id>
              <goals>
                <goal>install</goal>
                <goal>run</goal>
              </goals>
            </execution>
          </executions>
        </plugin>
    </plugins>
  </build>
</project>

插件項目與普通maven項目的核心區別在於pom.xml中:
1 packaing是:maven-plugin
2 依賴maven-plugin-api中定義進行maven插件實現

這里要注意:
maven-*-plugin的artifactId名稱被官方保留,自己使用時會報錯.
修改maven-plugin-api版本為3.0
刪除非必要的依賴其插件配置

  • 代碼編寫

代碼編寫:
1 自定義類繼承org.apache.maven.plugin.AbstractMojo
2 實現execute()方法
3 提供@goal標注

@goal是觸發execute()方法執行的自定義標識
參數定義可以使用我參考資料里的注釋方式,也可以使用注解方式.實際注釋方式更簡潔:
注釋方式:

    /**
     * @parameter property = "project.basedir"
     * @required
     * @readonly
     */
    private File basedir;

注解方式:
1 需要在pom.xml中引入注解依賴

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

使用方式

    @Parameter( defaultValue = "${project.build.directory}", property = "outputDir", required = true )
    private File outputDirectory;
  • 使用

代碼編寫完畢后,執行mvn clean install將插件安裝到本地,這樣其他項目就可以引用此插件.

引用方式:
pom.xml中添加如下插件配置

<build>
        <plugins>
            <plugin>
                <groupId>com.ll</groupId>
                <artifactId>loc-maven-plugin</artifactId>
                <version>1.0-SNAPSHOT</version>
                <executions>
                    <execution>
                        <phase>verify</phase>
                        <goals>
                            <goal>count</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <incloude>java</incloude>
                    <incloude>sql</incloude>
                </configuration>
            </plugin>
        </plugins>
    </build>

實際執行就可以觸發自定義插件的使用

  • 擴展

實際的代碼中使用了集成測試插件:maven-invoker-plugin.它是專門進行插件測試的插件.它的使用需要將使用插件的項目放到插件項目下的src/it目錄下(這個目錄是默認目錄,可以配置).實際插件pom.xml配置如下:

  <build>
    <plugins>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-invoker-plugin</artifactId>
          <version>3.1.0</version>
          <configuration>
            <cloneProjectsTo>${project.build.directory}/it</cloneProjectsTo>
            <postBuildHookScript>verify</postBuildHookScript>
            <goals>
              <goal>install</goal>
            </goals>
          </configuration>
          <executions>
            <execution>
              <id>integration-test</id>
              <goals>
                <goal>install</goal>
                <goal>run</goal>
              </goals>
            </execution>
          </executions>
        </plugin>
    </plugins>
  </build>

postBuildHookScript定義測試grooy腳本,groovy腳本如下:

File file = new File( basedir, "build.log" );

def countMain = false
def countTest = false

file.eachLine {
    if (it.contains("files size: 1 lines num: 7"))
        countMain = true;
    if (it.contains("files size: 0 lines num: 0"))
        countTest = true;
}

if(!countMain) {
    throw new RuntimeException("incorrect src/main/java count info");
}
if(!countTest) {
    throw new RuntimeException("incorrect src/test/java count info");
}

內容很簡單,就是預期的測試輸出內容定義,符合預期則提示成功,不符合則輸出失敗.

最終項目層級結構:

測試

在插件項目下執行: mvn clean install
執行效果:

D:\workfile\jdk\jdk11.0.13\bin\java.exe -Dmaven.multiModuleProjectDirectory=D:\git_repo\demo\loc-maven-plugin "-Dmaven.home=D:\workfile\ide\IntelliJ IDEA 2021.2\plugins\maven\lib\maven3" "-Dclassworlds.conf=D:\workfile\ide\IntelliJ IDEA 2021.2\plugins\maven\lib\maven3\bin\m2.conf" "-Dmaven.ext.class.path=D:\workfile\ide\IntelliJ IDEA 2021.2\plugins\maven\lib\maven-event-listener.jar" "-javaagent:D:\workfile\ide\IntelliJ IDEA 2021.2\lib\idea_rt.jar=50816:D:\workfile\ide\IntelliJ IDEA 2021.2\bin" -Dfile.encoding=UTF-8 -classpath "D:\workfile\ide\IntelliJ IDEA 2021.2\plugins\maven\lib\maven3\boot\plexus-classworlds-2.6.0.jar;D:\workfile\ide\IntelliJ IDEA 2021.2\plugins\maven\lib\maven3\boot\plexus-classworlds.license" org.codehaus.classworlds.Launcher -Didea.version=2021.2 clean install
[INFO] Scanning for projects...
[INFO] 
[INFO] ----------------------< com.ll:loc-maven-plugin >-----------------------
[INFO] Building loc-maven-plugin Maven Plugin 1.0-SNAPSHOT
[INFO] ----------------------------[ maven-plugin ]----------------------------
[INFO] 
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ loc-maven-plugin ---
[INFO] Deleting D:\git_repo\demo\loc-maven-plugin\target
[INFO] 
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ loc-maven-plugin ---
[INFO] Using 'utf8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory D:\git_repo\demo\loc-maven-plugin\src\main\resources
[INFO] 
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ loc-maven-plugin ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to D:\git_repo\demo\loc-maven-plugin\target\classes
[INFO] 
[INFO] --- maven-plugin-plugin:3.2:descriptor (default-descriptor) @ loc-maven-plugin ---
[INFO] Using 'utf8' encoding to read mojo metadata.
[INFO] Applying mojo extractor for language: java
[INFO] Mojo extractor for language: java found 1 mojo descriptors.
[INFO] Applying mojo extractor for language: bsh
[INFO] Mojo extractor for language: bsh found 0 mojo descriptors.
[INFO] Applying mojo extractor for language: java-annotations
[INFO] Mojo extractor for language: java-annotations found 0 mojo descriptors.
[INFO] 
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ loc-maven-plugin ---
[INFO] Using 'utf8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory D:\git_repo\demo\loc-maven-plugin\src\test\resources
[INFO] 
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ loc-maven-plugin ---
[INFO] No sources to compile
[INFO] 
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ loc-maven-plugin ---
[INFO] No tests to run.
[INFO] 
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ loc-maven-plugin ---
[INFO] Building jar: D:\git_repo\demo\loc-maven-plugin\target\loc-maven-plugin-1.0-SNAPSHOT.jar
[INFO] 
[INFO] --- maven-plugin-plugin:3.2:addPluginArtifactMetadata (default-addPluginArtifactMetadata) @ loc-maven-plugin ---
[INFO] 
[INFO] --- maven-invoker-plugin:3.1.0:install (integration-test) @ loc-maven-plugin ---
[INFO] Installing D:\git_repo\demo\loc-maven-plugin\pom.xml to D:\repository\com\ll\loc-maven-plugin\1.0-SNAPSHOT\loc-maven-plugin-1.0-SNAPSHOT.pom
[INFO] Installing D:\git_repo\demo\loc-maven-plugin\target\loc-maven-plugin-1.0-SNAPSHOT.jar to D:\repository\com\ll\loc-maven-plugin\1.0-SNAPSHOT\loc-maven-plugin-1.0-SNAPSHOT.jar
[INFO] 
[INFO] --- maven-invoker-plugin:3.1.0:run (integration-test) @ loc-maven-plugin ---
[INFO] Building: count-demo\pom.xml
[INFO] run post-build script verify.groovy
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.codehaus.groovy.reflection.CachedClass (file:/D:/repository/org/codehaus/groovy/groovy-all/2.4.8/groovy-all-2.4.8.jar) to method java.lang.Object.finalize()
WARNING: Please consider reporting this to the maintainers of org.codehaus.groovy.reflection.CachedClass
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
[INFO]           count-demo\pom.xml ............................... SUCCESS (2.7 s)
[INFO] -------------------------------------------------
[INFO] Build Summary:
[INFO]   Passed: 1, Failed: 0, Errors: 0, Skipped: 0
[INFO] -------------------------------------------------
[INFO] 
[INFO] --- maven-install-plugin:2.4:install (default-install) @ loc-maven-plugin ---
[INFO] Installing D:\git_repo\demo\loc-maven-plugin\target\loc-maven-plugin-1.0-SNAPSHOT.jar to D:\repository\com\ll\loc-maven-plugin\1.0-SNAPSHOT\loc-maven-plugin-1.0-SNAPSHOT.jar
[INFO] Installing D:\git_repo\demo\loc-maven-plugin\pom.xml to D:\repository\com\ll\loc-maven-plugin\1.0-SNAPSHOT\loc-maven-plugin-1.0-SNAPSHOT.pom
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  6.726 s
[INFO] Finished at: 2022-03-12T16:02:19+08:00
[INFO] ------------------------------------------------------------------------

Process finished with exit code 0

參考資料

maven實戰-徐曉斌
代碼示例


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM