ZetCode

Maven Exec 插件

最后修改时间:2025 年 6 月 11 日

Maven Exec 插件允许您从 Maven 运行 Java 程序和系统命令。它非常适合开发,可以在不构建 JAR 文件的情况下快速执行。

该插件支持两个目标:exec:java 用于运行 Java 类,exec:exec 用于执行系统命令或脚本。本教程将通过实际示例涵盖插件的配置和使用。

基本配置

要使用 Maven Exec 插件,请将其添加到 pom.xmlbuild 部分。以下是在 package 阶段运行 Java 主类的示例配置。

pom.xml
<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 应用程序。

src/main/java/com/example/MainApp.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 packagemvn exec:java 将执行此类,打印问候语以及任何传递的参数或系统属性。

传递参数

您可以通过命令行或在 pom.xml 中进行配置,将命令行参数传递给您的 Java 应用程序。

命令行
mvn exec:java -Dexec.mainClass="com.example.MainApp" -Dexec.args="arg1 arg2 arg3"

这将“arg1”、“arg2”和“arg3”传递给 main 方法。或者,在 pom.xml 中配置参数

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 中配置系统属性

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 插件允许您自定义运行应用程序时使用的类路径,从而控制包含哪些依赖项。

pom.xml
<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 命令或其他可执行文件。

pom.xml
<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 阶段运行不同的程序或类,例如运行一个主类和一个实用工具。

pom.xml
<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 脚本,展示了该插件的灵活性。

src/main/java/com/example/DataValidator.java
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 中配置

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 应用程序很有用。

pom.xml
<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 应用程序中访问,或者可以被脚本等外部程序访问。

src/main/java/com/example/EnvApp.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"

这将输出环境变量的值,演示如何将环境变量传递给您的应用程序。

工作目录配置

您可以为执行的程序指定工作目录,这会影响文件操作的执行位置。

pom.xml
<configuration>
    <mainClass>com.example.MainApp</mainClass>
    <workingDirectory>${project.basedir}/target</workingDirectory>
</configuration>

这会将工作目录设置为 target 文件夹,在执行期间访问生成的文件或输出时很有用。

错误处理和退出代码

Exec 插件可以处理程序退出代码来控制构建过程。例如,如果程序以非零代码退出,您可以使构建失败。

pom.xml
<configuration>
    <mainClass>com.example.MainApp</mainClass>
    <successCodes>
        <successCode>0</successCode>
        <successCode>1</successCode>
    </successCodes>
</configuration>

此配置将退出代码 0 和 1 视为成功,从而防止构建失败。以下是一个展示退出代码用法的示例:

src/main/java/com/example/ExitCodeApp.java
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 插件的最佳实践:

来源

Exec Maven 插件文档

在本文中,我们探讨了如何使用 Maven Exec 插件直接从 Maven 运行 Java 应用程序和外部程序,并提供了配置和故障排除的实际示例和最佳实践。

作者

我叫 Jan Bodnar,是一位热情的程序员,拥有丰富的编程经验。我自 2007 年以来一直撰写编程文章。迄今为止,我已撰写了 1400 多篇文章和 8 本电子书。我在编程教学方面拥有十多年的经验。

列出所有Java教程