别再只会 mvn install 了!深入拆解 Maven 插件核心原理

2025-12-12 0 723

一、Maven与Maven插件

确切的说,我们日常提及的“Maven”实际上只是Maven插件集合的核心框架。而插件才是执行实际操作的东西,插件可以用于:创建jar文件、创建war文件、编译代码、单元测试代码、创建项目文档等等。

几乎所有您能想到的在项目中执行的操作都是通过Maven插件实现的。而我们安装的maven仅仅是为插件的运行提供一个管理框架

我们在打开一个maven管理的工程时,通常能在其POM文件中看到这样的内容

<project>
    
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <skip>true</skip>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

这其中 plugins 的内容就是所谓的Maven插件。当然,Maven有自己的标准插件,所以即使一个项目没有显式的引用Maven插件,也能执行一些基础的mvn命令,如clean、compile等。但是这个时候是默认配置。

所以如果你想有自己的配置,或者是有特定的目标,就需要显示的指定与配置plugins 了。

二、maven 插件使用举例

1. flatten-maven-plugin

① 插件配置

以我们一个实际项目为例,由于项目比较大,而且多模块互相引用,所以使得jar包也嵌套层数过高,那么工程版本管理就很繁琐,这个时候我们就可以使用 flatten-maven-plugin 这个插件,这个插件的作用是将项目的依赖打平(flatten),将所有依赖的版本号都解析并嵌入到POM文件中

<build>
    <plugins>
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>flatten-maven-plugin</artifactId>
            <version>1.2.5</version>
            <configuration>
                <outputDirectory>${project.build.directory}</outputDirectory>
                <flattenMode>resolveCiFriendliesOnly</flattenMode>
                <updatePomFile>true</updatePomFile>
                <ignoreTransitiveDependencies>true</ignoreTransitiveDependencies>
            </configuration>
            <executions>
                <execution>
                    <id>flatten</id>
                    <phase>generate-resources</phase>
                    <goals>
                        <goal>flatten</goal>
                    </goals>
                </execution>
                <execution>
                    <id>flatten.clean</id>
                    <phase>clean</phase>
                    <goals>
                        <goal>clean</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

上面的一些配置解释如下:

  • outputDirectory:  指定扁平化后的 POM 文件输出的目录
  • flattenMode:  指定扁平化的模式为 resolveCiFriendliesOnly, 项目中可能含有 ${revision}、 ${sha1} 、 ${changelist} 这种占位符,可以在mvn命令中直接使用mvn -Drevision=2.0.0-SNAPSHOT clean package,来在命令中为这些占位符赋值,并进行后续操作
  • updatePomFile:  表示会更新生成的扁平化 POM 文件
  • ignoreTransitiveDependencies:  忽略传递依赖,确保这些依赖不被包含在最终的扁平化 POM 中

除此以外,我们还定义了两个 execution,分别用于执行 flatten 以及 clean 操作。这样配置后,当执行 mvn generate-resources 时,会触发 flatten 操作,将项目的依赖进行扁平化处理。而执行 mvn clean 时,会执行 clean 操作,清理生成的扁平化文件。

② 作用

当我们经过上述配置后,当我们进行打包等操作时,触发 generate-resources 步骤,就能正常运行的插件了。最终的结果就是在我们指定的目录下,产生了一个.flattened-pom.xml

图片

图片

图片

图片

而且其内部就是jar包的平铺形式

2. exec-maven-plugin

① 插件配置

这个插件要用于在构建过程中执行外部程序或脚本。通过这个插件,可以方便地在Maven项目构建过程中调用外部命令、执行Shell脚本等。一个最常见的作用就是,进行代码混淆

<build>
    <plugins>
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>exec-maven-plugin</artifactId>
            <executions>
                <execution>
                    <id>obfuscate</id>
                    <phase>package</phase>
                    <goals>
                        <goal>exec</goal>
                    </goals>
                    <configuration>
                        <executable>java</executable>
                        <arguments>
                            <argument>-jar</argument>
                            <argument>path/to/allatori.jar</argument>
                            <argument>-config</argument>
                            <argument>path/to/allatori-config.xml</argument>
                            <argument>-in</argument>
                            <argument>${project.build.directory}/${project.build.finalName}.jar</argument>
                            <argument>-out</argument>
                            <argument>${project.build.directory}/${project.build.finalName}-obfuscated.jar</argument>
                        </arguments>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

涉及的各个具体配置的含义如下:

  • :指定要执行的命令为java,表示使用Java来执行命令。

  • :配置执行的命令参数,具体含义如下:

    • -jar path/to/allatori.jar:指定执行的jar包为Allatori混淆工具的jar包路径。
    • -config path/to/allatori-config.xml:指定Allatori混淆工具所需的配置文件路径。
    • -in ${project.build.directory}/${project.build.finalName}.jar:指定待混淆的jar包路径。
    • -out ${project.build.directory}/${project.build.finalName}-obfuscated.jar:指定混淆后的jar包输出路径。

通过这样的配置,项目构建过程中会在package阶段执行命令,使用java -jar 这样的命令调用Allatori混淆工具,对我们的工程打包结果进行混淆处理。不难发现,这里其实还有一个关键的配置文件 allatori-config.xml

图片

图片

关于这个配置文件该怎么配,他的属性与作用,可以见官方文档: https://allatori.com/doc.html ,我们就不再赘述

② 作用

经过配置后,我们的编译的代码就会产生一些变化,比如变量名变成了VAR系列,当然,变化的多寡取决于我们上面的配置文件

图片

图片

图片

图片

当然,这里还有一个很特殊的点。就是使用 allatori 会有一个默认配置 synthetize-methods, 这个默认配置会让所有私有方法被标记为合成方法。而很多反编译器不展示合成方法,导致的结果就是反编译后看不到任何 private 方法

图片

图片

三、maven 插件原理

1. MOJO(Maven Plain Old Java Object)

谈及maven插件,就必须提及一个重要概念MOJO ,MOJO 是一个缩写,全称为 Maven Plain Old Java Object。MOJO 是 Maven 插件中的一个核心概念,它代表了一个具体的构建任务或目标(goal)。

每个 MOJO 都是一个 Java 类,实现了特定的构建逻辑,并且可以通过 Maven 的命令行或配置文件(如 pom.xml)来调用。

MOJO 的主要特点

Java 类:

MOJO 是一个普通的 Java 类,通常继承自 org.apache.maven.plugin.AbstractMojo 类。

这个类提供了许多有用的方法和属性,帮助你更方便地编写插件。

目标(Goal):

每个 MOJO 定义了一个或多个目标(goal),这些目标可以在 Maven 的生命周期中被调用。

目标是一个具体的构建任务,例如编译代码、打包、测试等。

注解:

MOJO 类和方法通常使用注解来提供元数据,例如 @Mojo 注解用于标记一个类为 MOJO,@Parameter 注解用于标记类的属性为插件配置参数。

配置参数:

MOJO 可以通过 pom.xml 或命令行接收配置参数,这些参数用于控制 MOJO 的行为。

例如, 元素可以用来配置 MOJO 的参数。

2. 通用的配置

知道了Mojo后,我们再回头看看插件,插件由一个或多个Mojo组成,其中一个Mojo映射到一个目标。

例如,您有一个Mojo,它对特定的URL执行查询,并带有指定的超时和选项列表。Mojo可能是这样的

@Mojo( name = \"query\" )
publicclass MyQueryMojo
    extends AbstractMojo
{
    @Parameter(property = \"query.url\", required = true)
    private String url;
    
    @Parameter(property = \"timeout\", required = false, defaultValue = \"50\")
    privateint timeout;
    
    @Parameter(property = \"options\")
    private String[] options;

@Override
    public void execute()
        throws MojoExecutionException
    {
        ...
    }
}

然后再要使用这个插件的位置,这样设置pom.xml

<project>
  ...
<build>
    <plugins>
      <plugin>
        <artifactId>maven-myquery-plugin</artifactId>
        <version>1.0</version>
        <configuration>
          <url>http://www.foobar.com/query</url>
          <timeout>10</timeout>
          <options>
            <option>one</option>
            <option>two</option>
            <option>three</option>
          </options>
        </configuration>
      </plugin>
    </plugins>
</build>
  ...
</project>

配置中的元素与Mojo中字段的名称相匹配。映射是直接的。url元素映射到url字段,timeout元素映射到timeout字段,options元素映射到options字段。映射机制可以通过检查字段的类型并确定是否可能有合适的映射来处理数组。

四、自定义Maven插件

1. 编写一个maven插件

比如我们想写一个名字叫 “hello-maven-plugin” 的maven插件,目的是提供一个sayHi方法,在编译时输出一个Hello, world。那么我们首先创建一个maven项目,然后这样设置pom文件

<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>sample.plugin</groupId>
    <artifactId>hello-maven-plugin</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>maven-plugin</packaging>
    <name>Sample Parameter-less Maven Plugin</name>
    <properties>
        <maven-plugin-tools.version>3.15.1</maven-plugin-tools.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.apache.maven</groupId>
            <artifactId>maven-plugin-api</artifactId>
            <version>3.9.9</version>
            <scope>provided</scope>
        </dependency>
        
        <dependency>
            <groupId>org.apache.maven.plugin-tools</groupId>
            <artifactId>maven-plugin-annotations</artifactId>
            <version>${maven-plugin-tools.version}</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-plugin-plugin</artifactId>
                    <version>${maven-plugin-tools.version}</version>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
</project>

然后我们的核心是建立一个类,如下 GreetingMojo.java

package org.example;

import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.Mojo;
/**
 * Says \"Hi\" to the user.
 *
 */
@Mojo(name = \"sayhi\")
public class GreetingMojo extends AbstractMojo
{
    @Override
    public void execute() throws MojoExecutionException
    {
        getLog().info(\"Hello, world.\");
    }
}

完成上述后,我们进行一次mvn install,把我们自己编写的这个插件上传到本地仓库中,以便被其他项目使用。

2. 直接执行

继上述我们写完自己的插件,并且install后,我们就能在其他项目里运用我们自己的这个插件了。比如我现在有一个项目,我在其pom文件里加上我们自己配置的插件

图片

图片

然后我们就看到我们这个项目可以使用自定义插件的功能了

图片

图片

双击 hello.sayhi 或者执行命令 mvn sample.plugin:hello-maven-plugin:1.0-SNAPSHOT:sayhi

图片

图片

3. 绑定周期

但是大部分时候,我们不会手动去执行 mvn sample.plugin:hello-maven-plugin:1.0-SNAPSHOT:sayhi 这种命令,而是希望在某个通用的动作时,他能够自动去执行。

比方说我们希望在清理编译结果之前他可以自动sayhI, 这个时候我们就可以写成这样

图片

图片

那么当我们运行clean的时候,就能看到他在clean之前,自动执行了sayhi

图片

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

申明:本文由第三方发布,内容仅代表作者观点,与本网站无关。对本文以及其中全部或者部分内容的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。本网发布或转载文章出于传递更多信息之目的,并不意味着赞同其观点或证实其描述,也不代表本网对其真实性负责。

左子网 编程相关 别再只会 mvn install 了!深入拆解 Maven 插件核心原理 https://www.zuozi.net/36026.html

常见问题
  • 1、自动:拍下后,点击(下载)链接即可下载;2、手动:拍下后,联系卖家发放即可或者联系官方找开发者发货。
查看详情
  • 1、源码默认交易周期:手动发货商品为1-3天,并且用户付款金额将会进入平台担保直到交易完成或者3-7天即可发放,如遇纠纷无限期延长收款金额直至纠纷解决或者退款!;
查看详情
  • 1、描述:源码描述(含标题)与实际源码不一致的(例:货不对板); 2、演示:有演示站时,与实际源码小于95%一致的(但描述中有”不保证完全一样、有变化的可能性”类似显著声明的除外); 3、发货:不发货可无理由退款; 4、安装:免费提供安装服务的源码但卖家不履行的; 5、收费:价格虚标,额外收取其他费用的(但描述中有显著声明或双方交易前有商定的除外); 6、其他:如质量方面的硬性常规问题BUG等。 注:经核实符合上述任一,均支持退款,但卖家予以积极解决问题则除外。
查看详情
  • 1、左子会对双方交易的过程及交易商品的快照进行永久存档,以确保交易的真实、有效、安全! 2、左子无法对如“永久包更新”、“永久技术支持”等类似交易之后的商家承诺做担保,请买家自行鉴别; 3、在源码同时有网站演示与图片演示,且站演与图演不一致时,默认按图演作为纠纷评判依据(特别声明或有商定除外); 4、在没有”无任何正当退款依据”的前提下,商品写有”一旦售出,概不支持退款”等类似的声明,视为无效声明; 5、在未拍下前,双方在QQ上所商定的交易内容,亦可成为纠纷评判依据(商定与描述冲突时,商定为准); 6、因聊天记录可作为纠纷评判依据,故双方联系时,只与对方在左子上所留的QQ、手机号沟通,以防对方不承认自我承诺。 7、虽然交易产生纠纷的几率很小,但一定要保留如聊天记录、手机短信等这样的重要信息,以防产生纠纷时便于左子介入快速处理。
查看详情

相关文章

猜你喜欢
发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务