<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>
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


<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><!-- 指定执行的命令为java -->
<arguments>
<argument>-jar</argument>
<argument>path/to/allatori.jar</argument><!-- Allatori的jar包路径 -->
<argument>-config</argument>
<argument>path/to/allatori-config.xml</argument><!-- Allatori混淆配置文件路径 -->
<argument>-in</argument>
<argument>${project.build.directory}/${project.build.finalName}.jar</argument><!-- 待混淆的jar包路径 -->
<argument>-out</argument>
<argument>${project.build.directory}/${project.build.finalName}-obfuscated.jar</argument><!-- 混淆后的jar包输出路径 -->
</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
-
<executable>:指定要执行的命令为java,表示使用Java来执行命令。 -
<arguments>:配置执行的命令参数,具体含义如下: -
-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 ,我们就不再赘述


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

谈及maven插件,就必须提及一个重要概念MOJO ,MOJO 是一个缩写,全称为 Maven Plain Old Java Object。MOJO 是 Maven 插件中的一个核心概念,它代表了一个具体的构建任务或目标(goal)。
org.apache.maven.plugin.AbstractMojo 类。
这个类提供了许多有用的方法和属性,帮助你更方便地编写插件。
@Mojo 注解用于标记一个类为 MOJO,@Parameter 注解用于标记类的属性为插件配置参数。
pom.xml 或命令行接收配置参数,这些参数用于控制 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
{
...
}
}
<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>
Hello, world比如我们想写一个名字叫 “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 on annotations -->
<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然后我们的核心是建立一个类,如下 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,把我们自己编写的这个插件上传到本地仓库中,以便被其他项目使用。


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

mvn sample.plugin:hello-maven-plugin:1.0-SNAPSHOT:sayhi 这种命令,而是希望在某个通用的动作时,他能够自动去执行。


往期推荐
Java + LangChain = 王炸!
盘一盘 XXL-JOB 中那些惊艳的架构设计
我用 Java 把二维码玩出花了
2025 年 11 月编程语言排行榜|C# 要翻身超Java?
SpringBoot中这10个神仙功能,惊艳到我了!
阿里又开源了一个顶级 Java 项目!

