自定义 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实战-徐晓斌
代码示例

posted @ 2022-03-12 16:39  橙木鱼  阅读(826)  评论(0编辑  收藏  举报