51

我有一组项目,它们都需要在构建期间运行相同系列的 Maven 插件执行。我想避免在每个项目中重新声明所有这些配置,所以我让它们都继承自父 pom“模板”项目,该项目仅包含那些插件执行(8 个不同的 mojos)。但我希望这些插件执行只在子项目上运行,而不是在 Maven 构建期间在父项目上运行。

我尝试了四种不同的方式来完成这件事,每种方式都有我不喜欢的副作用。

  1. 在父 pom 的元素中声明插件执行,build/plugins并使用 properties-maven-plugin打开skip父项目中其他插件的属性。这不起作用,因为插件目标之一(maven-dependency-plugin:build-classpath)没有skip属性。

  2. build/pluginManagement在父 pom 的元素中声明插件执行。build/plugins不幸的是,这需要我在每个子项目的 pom 元素中重新声明八个插件中的每一个,例如:

    <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
    </plugin>
    ...
    

    如果我需要更改模板 pom.xml 中的插件,这太重复了,而且有问题。

  3. 在父 pom 中的配置文件中声明插件执行,该文件因缺少文件而激活(nobuild.txtpom 中确实存在,因此插件不会在那里执行):

    <profiles>
        <profile>
            <activation>
                <file>
                    <missing>nobuild.txt</missing>
                </file>
            </activation>
            <build>
                ....
            </build>
        </profile>
    </profiles>
    

    这在大多数情况下都有效,除了missing元素中的文件路径似乎基于当前工作目录而不是基于项目的项目。这打破了我希望能够做的一些多模块构建。 编辑:澄清一下,父“模板”项目实际上本身就是多模块项目中的一个模块,并且当我尝试例如mvn install在根上执行时构建中断。项目结构如下:

    + job
    |- job-core
    |- job-template
    |- job1                   inherits from job-template
    |- job2                   inherits from job-template
    
  4. 设置自定义生命周期和打包。这似乎允许我将插件绑定到生命周期阶段,但不指定任何配置

那么,是否有另一种方法来指定一组可以在多个项目中重用的 Maven 插件执行(在每个项目的 pom 中重复最少)?

4

5 回答 5

27

这是第五种方式。我认为它有最小的缺点:没有配置文件,没有自定义生命周期,在子 POM 中没有声明,对插件没有“跳过”要求。

从https://stackoverflow.com/a/14653088/2053580复制它——非常感谢最终用户

<build>
    <pluginManagement>
        <plugins>
            <plugin>
                <!-- Main declaration and configuration of the plugin -->
                <!-- Will be inherited by children -->
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-checkstyle-plugin</artifactId>
                <version>2.9.1</version>
                <executions>
                    <execution>
                        <!--This must be named-->
                        <id>checkstyle</id>
                        <phase>compile</phase>
                        <goals>
                            <goal>check</goal>
                        </goals>
                    </execution>
                </executions>
                <!-- You may also use per-execution configuration block -->
                <configuration...>
            </plugin>
        </plugins>
    </pluginManagement>
    <plugins>
        <plugin>
            <!-- This declaration makes sure children get plugin in their lifecycle -->
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-checkstyle-plugin</artifactId>
            <!-- Configuration won't be propagated to children -->
            <inherited>false</inherited>
            <executions>
                <execution>
                    <!--This matches and thus overrides execution defined above -->
                    <id>checkstyle</id>
                    <!-- Unbind from lifecycle for this POM -->
                    <phase>none</phase>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>
于 2018-12-07T08:56:14.520 回答
11

我最终编写了自己的插件,该插件利用mojo-executor来调用其他 mojo。这使我能够 1) 集中构建配置和 2) 最大限度地减少在每个子项目中重复的配置数量。

(如果您对这一切的原因感到好奇:每个子项目都是一个将从命令行执行的作业。构建设置了一个调用者 shell 脚本并将其附加到构建中,以便将其签入我们的工件存储库。部署脚本稍后将它们拉到它们将运行的机器上。)

模板项目的 pom 的相关部分:

<project ...>
    <parent> ... </parent>
    <artifactId>job-template</artifactId>
    <packaging>pom</packaging>
    <name>job project template</name>
    <build>
        <pluginManagement>
            <plugin>
                <groupId>...</groupId>
                <artifactId>job-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <id>generate-sources-step</id>
                        <goals><goal>job-generate-sources</goal></goals>
                    </execution>
                    <execution>
                        <id>package-step</id>
                        <goals><goal>job-package</goal></goals>
                    </execution>
                    ... (a couple more executions) ...
                </executions>
            </plugin>
        </pluginManagement>
    </build>
</project>

不得不创建一个新的 maven-plugin 项目(job-maven-plugin)。Pom 看起来像:

<project ...>
    <parent> ... </parent>
    <artifactId>job-maven-plugin</artifactId>
    <packaging>maven-plugin</packaging>
    <name>job maven executor plugin</name>
    <dependencies>
        <dependency>
            <groupId>org.twdata.maven</groupId>
            <artifactId>mojo-executor</artifactId>
            <!-- version 1.5 supports Maven 2, while version 2.0 only supports Maven 3 -->
            <version>1.5</version>
        </dependency>
    </dependencies>
</project>

正如您从模板项目中看到的那样,我的插件中有多个 mojo(每个阶段一个需要发生的事情)。例如,job-package mojo 绑定到 package 阶段并使用 mojo-executor 库来运行另外两个 mojo(它们只是附加了一些构建工件):

/**
 * @goal job-package
 * @phase package
 */
public class PackageMojo extends AbstractMojo {
    /**
     * @parameter expression="${project}"
     * @required
     * @readonly
     */
    protected MavenProject project;
    /**
     * @parameter expression="${session}"
     * @required
     * @readonly
     */
    protected MavenSession session;
    /**
     * @component
     * @required
     */
    protected PluginManager pluginManager;

    @Override
    public void execute() throws MojoExecutionException, MojoFailureException {
        ExecutionEnvironment environment = executionEnvironment(project, session, pluginManager);

        // Attach script as a build artifact
        executeMojo(
            plugin(
                groupId("org.codehaus.mojo"),
                artifactId("build-helper-maven-plugin"),
                version("1.7")
            ),
            goal("attach-artifact"),
            configuration(
                element("artifacts",
                    element("artifact",
                        element("file", "${project.build.directory}/script.shl"),
                        element("type", "shl")
                    )
                )
            ),
            environment
        );

        // Zip up the jar and script as another build artifact
        executeMojo(
            plugin(
                groupId("org.apache.maven.plugins"),
                artifactId("maven-assembly-plugin"),
                version("2.3")
            ),
            goal("single"),
            configuration(
                element("descriptors",
                    element("descriptor", "${project.build.directory}/job/descriptor.xml")
                )
            ),
            environment
        );
    }
}

然后,在子项目中,我只需要引用一次插件。在我看来,这比在每个子项目中重复每个幕后插件要好得多(这不可接受地增加了 pom 之间的耦合)。如果我以后想在构建过程中添加一个 mojo 执行,我只需要修改一个地方并增加一个版本号。子项目的 pom 看起来像:

<project ...>
    <parent>
        <groupId> ... </groupId>
        <artifactId>job-template</artifactId>
        <version> ... </version>
        <relativePath>../job-template</relativePath>
    </parent>
    <artifactId>job-testjob</artifactId>
    <name>test job</name>
    <build>
        <plugins>
            <plugin>
                <groupId> ... </groupId>
                <artifactId>job-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

此外,整个多模块目录结构现在看起来像这样:

+- job
  +- job-core
  +- job-maven-plugin
  +- job-template
  +- job-testjob1               (inherits from job-template)
  +- job-testjob2               (inherits from job-template)

在我看来,这个解决方案并不完全是最佳的,因为我现在将插件配置嵌入到一系列 mojos 而不是 pom 中,但它满足了我的目标,即集中配置并最大限度地减少子项目 pom 之间的重复。

(最后一点:我刚刚发现maven-aggregate-plugin似乎允许在 pom 中对多个插件执行进行分组。这可能以稍微更理想的方式解决了问题,但我没有心情重做最后一个几个小时的工作。虽然可能对其他人有益。)

于 2012-10-17T23:52:54.370 回答
5

就我个人而言,我会选择解决方案 2。重复次数最少,如果可能,您应该尽量避免配置文件,以避免开始记录需要为哪些项目激活哪些配置文件。

只需简单地执行一个mvn (clean) install.

于 2012-10-17T15:11:53.197 回答
3

这是我在寻找相同问题的解决方案时发现的另一个选项。我在这里发布它是因为这已经是一个很好的选项集合 - 希望它可以帮助其他人不要花费数小时来解决这个问题:

鉴于插件具有跳过执行的选项,可以在父 pom(部分)中打开该选项,并将“继承”标志设置为 false,以便它不会传播给子代:

<plugin>
    <artifactId>maven-assembly-plugin</artifactId>
    <executions>
        <execution>
            <id>make-assembly</id>
            <phase>package</phase>
            <goals>
                <goal>single</goal>
            </goals>
            <inherited>true</inherited>
            <configuration>
               ...
            </configuration>
        </execution>
    </executions>
    <!-- Skip plugin execution for parent pom but enable it for all children -->
    <configuration>
        <skipAssembly>true</skipAssembly>
    </configuration>
    <inherited>false</inherited>
</plugin>

虽然当我第一次阅读这个解决方案时,我对它持怀疑态度,但它对我有用——至少对于程序集插件来说是这样。

于 2017-05-18T10:00:03.573 回答
1

另一种选择:您可以更改执行绑定到不存在值的阶段,而不是使用“跳过”属性,例如never.

<inherited>false</inherited>这与@Timi 建议的方法一起使用非常好

于 2017-10-05T12:55:44.613 回答