Maven Exec 插件
最后修改时间:2025 年 6 月 11 日
Maven Exec 插件允许您从 Maven 运行 Java 程序和系统命令。它非常适合开发,可以在不构建 JAR 文件的情况下快速执行。
该插件支持两个目标:exec:java 用于运行 Java 类,exec:exec 用于执行系统命令或脚本。本教程将通过实际示例涵盖插件的配置和使用。
基本配置
要使用 Maven Exec 插件,请将其添加到 pom.xml 的 build 部分。以下是在 package 阶段运行 Java 主类的示例配置。
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>exec-example</artifactId>
<version>1.0.0</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>run-app</id>
<phase>package</phase>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>com.example.MainApp</mainClass>
<cleanupDaemonThreads>false</cleanupDaemonThreads>
</configuration>
</plugin>
</plugins>
</build>
</project>
<mainClass>com.example.MainApp</mainClass>
这指定了要执行的主方法的 Java 类的完全限定名称。cleanupDaemonThreads 选项确保在关闭期间正确处理线程。
运行应用程序
您可以使用 exec:java 目标运行应用程序,如果未在 POM 中配置,则可以通过系统属性指定主类。
mvn exec:java -Dexec.mainClass="com.example.MainApp"
如果插件已在 pom.xml 中配置并绑定到 package 阶段,只需运行
mvn package
这将编译代码并执行已配置的主类。以下是一个演示的示例 Java 应用程序。
package com.example;
public class MainApp {
public static void main(String[] args) {
System.out.println("Hello from Maven Exec Plugin!");
for (String arg : args) {
System.out.println("Argument: " + arg);
}
String prop = System.getProperty("app.name", "Unknown");
System.out.println("App Name: " + prop);
}
}
运行 mvn package 或 mvn exec:java 将执行此类,打印问候语以及任何传递的参数或系统属性。
传递参数
您可以通过命令行或在 pom.xml 中进行配置,将命令行参数传递给您的 Java 应用程序。
mvn exec:java -Dexec.mainClass="com.example.MainApp" -Dexec.args="arg1 arg2 arg3"
这将“arg1”、“arg2”和“arg3”传递给 main 方法。或者,在 pom.xml 中配置参数
<configuration>
<mainClass>com.example.MainApp</mainClass>
<arguments>
<argument>input.txt</argument>
<argument>output.txt</argument>
</arguments>
</configuration>
这些参数会传递给 main 方法的 String[] args 参数,这对于文件名、标志或其他运行时输入很有用。
系统属性
可以传递系统属性来定制 JVM 或应用程序的行为。这可以通过命令行或在 pom.xml 中完成。
mvn exec:java -Dexec.mainClass="com.example.MainApp" \
-Dapp.name="MyApp" -Denv=dev
或者,在 pom.xml 中配置系统属性
<configuration>
<mainClass>com.example.MainApp</mainClass>
<systemProperties>
<property>
<key>app.name</key>
<value>MyApp</value>
</property>
<property>
<key>env</key>
<value>dev</value>
</property>
</systemProperties>
</configuration>
这些属性可以通过 System.getProperty 在您的 Java 代码中访问,如上面 MainApp 示例所示。
类路径配置
Exec 插件允许您自定义运行应用程序时使用的类路径,从而控制包含哪些依赖项。
<configuration>
<mainClass>com.example.MainApp</mainClass>
<classpathScope>runtime</classpathScope>
<includePluginDependencies>false</includePluginDependencies>
<includeProjectDependencies>true</includeProjectDependencies>
<additionalClasspathElements>
<additionalClasspathElement>${project.basedir}/lib/extra.jar</additionalClasspathElement>
</additionalClasspathElements>
</configuration>
<classpathScope>runtime</classpathScope>
定义要包含的依赖项范围(例如,compile、runtime、test)。includePluginDependencies 控制是否包含插件依赖项,而 additionalClasspathElements 添加自定义 JAR。
执行外部程序
exec:exec 目标运行系统命令或脚本,例如 Python 脚本、shell 命令或其他可执行文件。
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>run-script</id>
<phase>generate-resources</phase>
<goals>
<goal>exec</goal>
</goals>
</execution>
</executions>
<configuration>
<executable>python3</executable>
<arguments>
<argument>${project.basedir}/scripts/process.py</argument>
<argument>--input</argument>
<argument>data.txt</argument>
</arguments>
</configuration>
</plugin>
此示例在 generate-resources 阶段运行 Python 脚本。executable 必须在系统 PATH 中可用。
多重执行
您可以配置多个执行,以便在不同的 Maven 阶段运行不同的程序或类,例如运行一个主类和一个实用工具。
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>run-main</id>
<phase>package</phase>
<goals>
<goal>java</goal>
</goals>
<configuration>
<mainClass>com.example.MainApp</mainClass>
<arguments>
<argument>start</argument>
</arguments>
</configuration>
</execution>
<execution>
<id>run-tool</id>
<phase>verify</phase>
<goals>
<goal>java</goal>
</goals>
<configuration>
<mainClass>com.example.DataValidator</mainClass>
<arguments>
<argument>check</argument>
</arguments>
</configuration>
</execution>
<execution>
<id>run-script</id>
<phase>process-resources</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>bash</executable>
<arguments>
<argument>${project.basedir}/scripts/cleanup.sh</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
此配置在不同阶段运行了一个 Java 主类、一个验证工具和一个 shell 脚本,展示了该插件的灵活性。
package com.example;
public class DataValidator {
public static void main(String[] args) {
System.out.println("Running DataValidator with args: " + String.join(", ", args));
// Simulate validation logic
boolean valid = "check".equals(args.length > 0 ? args[0] : "");
System.out.println("Data validation: " + (valid ? "Success" : "Failure"));
}
}
这个 DataValidator 类模拟了一个验证过程,打印传递给它的参数。您可以使用以下命令运行整个 Maven 构建:
$ mvn package
这将按顺序执行所有配置的执行,运行主类、数据验证器和 shell 脚本。
调试支持
Exec 插件通过传递调试标志来支持 JVM 调试。这对于故障排除或在 IDE 中单步执行代码非常有用。
mvn exec:java -Dexec.mainClass="com.example.MainApp" \
-Dexec.jvmArgs="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005"
或在 pom.xml 中配置
<configuration>
<mainClass>com.example.MainApp</mainClass>
<jvmArguments>
<jvmArgument>-Xdebug</jvmArgument>
<jvmArgument>-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005</jvmArgument>
</jvmArguments>
</configuration>
这将以调试模式启动 JVM,监听端口 5005,允许您连接调试器(例如 IntelliJ IDEA 或 Eclipse)。
环境变量
您可以为执行的程序设置环境变量,这对于配置外部工具或 Java 应用程序很有用。
<configuration>
<mainClass>com.example.MainApp</mainClass>
<environmentVariables>
<JAVA_HOME>/usr/lib/jvm/java-17</JAVA_HOME>
<APP_ENV>development</APP_ENV>
</environmentVariables>
</configuration>
这些变量可以通过 System.getenv 在 Java 应用程序中访问,或者可以被脚本等外部程序访问。
package com.example;
public class EnvApp {
public static void main(String[] args) {
String env = System.getenv("APP_ENV");
System.out.println("Environment: " + (env != null ? env : "Not set"));
}
}
上面的代码检索 APP_ENV 变量,打印其值或指示它未设置。使用以下命令运行它:
mvn exec:java -Dexec.mainClass="com.example.EnvApp"
这将输出环境变量的值,演示如何将环境变量传递给您的应用程序。
工作目录配置
您可以为执行的程序指定工作目录,这会影响文件操作的执行位置。
<configuration>
<mainClass>com.example.MainApp</mainClass>
<workingDirectory>${project.basedir}/target</workingDirectory>
</configuration>
这会将工作目录设置为 target 文件夹,在执行期间访问生成的文件或输出时很有用。
错误处理和退出代码
Exec 插件可以处理程序退出代码来控制构建过程。例如,如果程序以非零代码退出,您可以使构建失败。
<configuration>
<mainClass>com.example.MainApp</mainClass>
<successCodes>
<successCode>0</successCode>
<successCode>1</successCode>
</successCodes>
</configuration>
此配置将退出代码 0 和 1 视为成功,从而防止构建失败。以下是一个展示退出代码用法的示例:
package com.example;
public class ExitCodeApp {
public static void main(String[] args) {
System.out.println("Running ExitCodeApp");
if (args.length > 0 && "fail".equals(args[0])) {
System.exit(2); // Non-success exit code
} else {
System.exit(0); // Success exit code
}
}
}
如果传递了“fail”参数,此应用程序将以代码 2 退出,否则以代码 0 退出。您可以使用 Exec 插件运行它来查看如何处理退出代码。
使用以下命令运行
mvn exec:java -Dexec.mainClass="com.example.ExitCodeApp" -Dexec.args="fail"
如果没有 successCodes,非零退出代码将导致构建失败。
最佳实践
以下是有效使用 Maven Exec 插件的最佳实践:
-
显式配置插件 - 在
pom.xml中定义执行和配置,以实现一致的构建。 - 使用特定阶段 - 将执行绑定到适当的 Maven 阶段(例如,package、verify),以便与构建生命周期集成。
- 最小化命令行覆盖 - 对于可重现性,优先使用 POM 配置而非命令行参数。
-
正确处理线程 - 将
cleanupDaemonThreads设置为 false,以避免后台线程出现问题。 - 验证可执行文件 - 确保系统命令(例如 python3)在 PATH 中可用,以避免执行失败。
- 明智地使用调试 - 仅在需要时启用调试模式,以避免生产构建中的性能开销。
-
监控退出代码 - 配置
successCodes来处理预期的退出代码,并防止不必要的构建失败。
来源
在本文中,我们探讨了如何使用 Maven Exec 插件直接从 Maven 运行 Java 应用程序和外部程序,并提供了配置和故障排除的实际示例和最佳实践。
作者
列出所有Java教程。