找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

458

积分

0

好友

66

主题
发表于 2025-11-27 02:04:28 | 查看: 24| 回复: 0

一、Maven与Maven插件

在日常开发中,我们常说的"Maven"实际上指的是其核心框架,它主要负责管理插件的执行。而真正执行具体操作的是各种Maven插件,这些插件可以用于创建JAR文件、编译代码、运行单元测试、生成项目文档等任务。

几乎所有项目构建相关的操作都是通过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提供了一系列标准插件,因此即使项目没有显式声明插件,也能执行clean、compile等基础命令,不过这些操作使用的是默认配置。

如果需要进行个性化配置或实现特定功能,就需要显式地声明和配置plugins。

二、Maven插件使用实例

1. flatten-maven-plugin
① 插件配置

在多模块项目中,当模块间依赖关系复杂、嵌套层次过深时,版本管理会变得相当繁琐。这时可以使用flatten-maven-plugin插件,它的作用是将项目依赖进行扁平化处理,将所有依赖版本号解析并嵌入到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}等占位符
  • updatePomFile:更新生成的扁平化POM文件
  • ignoreTransitiveDependencies:忽略传递依赖,确保这些依赖不包含在最终的扁平化POM中

配置中还定义了两个execution,分别用于执行flatten和clean操作。当执行mvn generate-resources时触发flatten操作,执行mvn clean时清理生成的扁平化文件。

② 功能效果

完成上述配置后,在打包过程中触发generate-resources阶段,插件就会正常执行。最终在指定目录下生成.flattened-pom.xml文件,其中包含了所有依赖的平铺形式展示。

图片 图片

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>

配置参数详解:

  • <executable>:指定执行的命令为java
  • <arguments>:配置执行命令的参数
    • -jar path/to/allatori.jar:指定Allatori混淆工具的JAR包路径
    • -config path/to/allatori-config.xml:指定混淆配置文件路径
    • -in参数:指定待混淆的JAR包路径
    • -out参数:指定混淆后的JAR包输出路径

通过这样的配置,在package阶段会执行命令调用Allatori混淆工具对工程打包结果进行处理。这里还需要关键的配置文件allatori-config.xml。

图片

关于配置文件的详细属性和用法,可以参考官方文档:https://allatori.com/doc.html

② 功能效果

配置完成后,编译代码会发生相应变化,比如变量名被替换为VAR系列。具体变化程度取决于配置文件的设置。

图片 图片

需要注意的是,allatori有一个默认配置synthetize-methods,会将所有私有方法标记为合成方法。由于很多反编译器不展示合成方法,导致反编译后看不到任何private方法。

图片

三、Maven插件原理

1. MOJO(Maven Plain Old Java Object)

MOJO是Maven插件中的核心概念,全称为Maven Plain Old Java Object。每个MOJO代表一个具体的构建任务或目标(goal)。

每个MOJO都是一个Java类,实现特定的构建逻辑,可以通过Maven命令行或POM配置文件调用。

MOJO的主要特性

Java类结构: MOJO是一个普通的Java类,通常继承自org.apache.maven.plugin.AbstractMojo类,该类提供了许多有用的方法和属性。

构建目标: 每个MOJO定义一个或多个目标,这些目标可以在Maven生命周期中被调用,执行如编译代码、打包、测试等具体任务。

注解支持: MOJO类和方法使用注解提供元数据,如@Mojo注解标记类为MOJO,@Parameter注解标记类的属性为插件配置参数。

参数配置: MOJO可以通过pom.xml或命令行接收配置参数,使用<configuration>元素配置MOJO参数。

2. 通用配置机制

MOJO组成了插件的核心,每个MOJO映射到一个具体目标。例如,一个执行URL查询的MOJO可能如下定义:

@Mojo(name = "query")
public class MyQueryMojo extends AbstractMojo {
    @Parameter(property = "query.url", required = true)
    private String url;

    @Parameter(property = "timeout", required = false, defaultValue = "50")
    private int timeout;

    @Parameter(property = "options")
    private String[] options;

    @Override
    public void execute() throws MojoExecutionException {
        // 执行逻辑
    }
}

在POM文件中的配置方式:

<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中字段名称直接映射,映射机制通过检查字段类型自动处理数组等复杂结构。

四、自定义Maven插件开发

1. 编写Maven插件

假设我们要开发一个名为"hello-maven-plugin"的插件,提供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;

@Mojo(name = "sayhi")
public class GreetingMojo extends AbstractMojo {
    @Override
    public void execute() throws MojoExecutionException {
        getLog().info("Hello, world.");
    }
}

完成代码编写后,执行mvn install将插件安装到本地仓库,供其他项目使用。

2. 直接执行插件

安装完成后,在其他项目的POM文件中配置自定义插件:

图片

配置后即可使用自定义插件功能:

图片

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

图片

3. 绑定生命周期

通常我们不会手动执行复杂命令,而是希望插件在特定阶段自动执行。例如,希望在清理编译结果前自动执行sayhi,可以这样配置:

图片

运行clean时,会在clean之前自动执行sayhi:

图片

通过自定义Maven插件的开发,可以极大地扩展Maven的功能,满足特定项目的构建需求。




上一篇:MySQL索引失效深度解析:7种常见场景与优化实战
下一篇:Blinko开源AI卡片笔记实战:自托管闪念管理与智能检索优化
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区(YunPan.Plus) ( 苏ICP备2022046150号-2 )

GMT+8, 2025-12-7 09:17 , Processed in 0.071344 second(s), 39 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 CloudStack.

快速回复 返回顶部 返回列表