Plugin Management in Maven – Maven中的插件管理

最后修改: 2021年 7月 17日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

Apache Maven is a powerful tool that uses plugins to automate and perform all the build and reporting tasks in a Java project.

Apache Maven是一个强大的工具,它使用插件来自动化并执行Java项目中的所有构建和报告任务。

However, there are likely to be several of these plugins used in the build along with different versions and configurations, especially in a multi-module project. This can lead to problems of complex POM files with redundant or duplicate plugin artifacts as well as configurations scattered across various child projects.

然而,在构建过程中很可能会有几个这样的插件,同时还有不同的版本和配置,尤其是在多模块项目中。这可能会导致复杂的POM文件中出现冗余或重复的插件工件,以及分散在各个子项目中的配置问题。

In this article, we’ll see how to use Maven’s plugin management mechanism to handle such issues and effectively maintain plugins across the whole project.

在本文中,我们将看到如何使用Maven的插件管理机制来处理此类问题,并在整个项目中有效维护插件。

2. Plugin Configuration

2.插件配置

Maven has two types of plugins:

Maven有两种类型的插件。

  • Build – executed during the build process. Examples include Clean, Install, and Surefire plugins. These should be configured in the build section of the POM.
  • Reporting – executed during site generation to produce various project reports. Examples include Javadoc and Checkstyle plugins. These are configured in the reporting section of the project POM.

Maven plugins provide all the useful functionalities required to execute and manage the project build.

Maven插件提供了执行和管理项目构建所需的所有有用功能。

For example, we can declare the Jar plugin in the POM:

例如,我们可以在POM中声明Jar>插件。

<build>
    ....
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>3.2.0</version>
            ....
        </plugin>
    ....
    </plugins>
</build>

Here, we’ve included the plugin in the build section to add the capability to compile our project into a jar.

在这里,我们在build部分包含了这个插件,以增加将我们的项目编译为jar的能力。

3. Plugin Management

3.插件管理

In addition to the plugins, we can also declare plugins in the pluginManagement section of the POM. This contains the plugin elements in much the same way as we saw previously. However, by adding the plugin in the pluginManagement section, it becomes available to this POM, and all inheriting child POMs.

除了plugin,我们还可以在POM的pluginManagement部分声明插件。这包含了plugin元素,与我们之前看到的方式基本相同。然而,通过在pluginManagement部分添加插件,它对这个POM和所有继承的子POM都可用

This means that any child POMs will inherit the plugin executions simply by referencing the plugin in their plugin section. All we need to do is add the relevant groupId and artifactId, without having to duplicate the configuration or manage the version.

这意味着任何子POM将继承插件的执行,只需在其plugin部分引用该插件。我们需要做的就是添加相关的groupIdartifactId,而不需要重复配置或管理版本。

Similar to the dependency management mechanism, this is particularly useful in multi-module projects as it provides a central location to manage plugin versions and any related configuration.

依赖性管理机制类似,这在多模块项目中特别有用,因为它提供了一个管理插件版本和任何相关配置的中央位置。

4. Example

4.例子

Let’s start by creating a simple multi-module project with two submodules. We’ll include the Build Helper Plugin in the parent POM which contains several small goals to assist with the build lifecycle. In our example, we’ll use it to copy some additional resources to the project output for a child project.

让我们首先创建一个简单的多模块项目,其中有两个子模块。我们将在父级POM中包括构建帮助插件,它包含几个小目标,以协助构建生命周期。在我们的例子中,我们将使用它来复制一些额外的资源到子项目的项目输出中。

4.1. Parent POM Configuration

4.1.母体POM配置

First, we’ll add the plugin to the pluginManagement section of the parent POM:

首先,我们将插件添加到父POM的pluginManagement部分。

<pluginManagement>
    <plugins>
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>build-helper-maven-plugin</artifactId>
            <version>3.3.0</version>
            <executions>
                <execution>
                    <id>add-resource</id>
                    <phase>generate-resources</phase>
                    <goals>
                        <goal>add-resource</goal>
                    </goals>
                    <configuration>
                        <resources>
                            <resource>
                                <directory>src/resources</directory>
                                <targetPath>json</targetPath>
                            </resource>
                        </resources>
                    </configuration>
                </execution>
            </executions>
        </plugin>
   </plugins>
</pluginManagement>

This binds the plugin’s add-resource goal to the generate-resources phase in the default POM lifecycle. We’ve also specified the src/resources directory containing the additional resources. The plugin execution will copy these resources to the target location in the project output, as required.

这将插件的添加资源目标与默认POM生命周期中的生成资源阶段绑定。我们还指定了包含额外资源的src/resources目录。插件的执行将根据需要把这些资源复制到项目输出的目标位置。

Next, let’s run the maven command to ensure that the configuration is valid and the build is successful:

接下来,让我们运行maven命令,确保配置有效,构建成功。

$ mvn clean test

After running this, the target location does not contain the expected resources yet.

运行这个后,目标位置还不包含预期的资源。

4.2. Child POM Configuration

4.2.子POM配置

Now, let’s reference this plugin from the child POM:

现在,让我们从子POM中引用这个插件。

<build>
    <plugins>
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>build-helper-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

Similar to dependency management, we don’t declare the version or any plugin configuration. Instead, child projects inherit these values from the declaration in the parent POM.

与依赖性管理类似,我们不声明版本或任何插件配置。相反,子项目从父POM中的声明继承这些值。

Finally, let’s run the build again and see the output:

最后,让我们再次运行构建,看看输出。

....
[INFO] --- build-helper-maven-plugin:3.3.0:add-resource (add-resource) @ submodule-1 ---
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ submodule-1 ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.

[INFO] Copying 1 resource to json
....

Here, the plugin executes during the build but only in the child project with the corresponding declaration. As a result, the project output now contains the additional resources from the specified project location, as expected.

在这里,该插件在构建过程中执行,但只在有相应声明的子项目中执行。结果是,项目输出现在包含了来自指定项目位置的额外资源,正如预期的那样。

We should note that only the parent POM contains the plugin declaration and configuration whilst the child projects just reference this, as needed.

我们应该注意到,只有父级POM包含插件声明和配置,而子项目只是根据需要引用它。

The child projects are free to modify the inherited configuration if required.

如果需要,子项目可以自由地修改继承的配置

5. Core Plugins

5.核心插件

There are some Maven core plugins that are used as part of the build lifecycle, by default. For example, the clean and compiler plugins don’t need to be declared explicitly.

有一些Maven 核心插件被默认为构建生命周期的一部分而使用。例如,cleancompiler插件就不需要明确声明。

We can, however, explicitly declare and configure these in the pluginManagement element in the POM. The main difference is that the core plugin configuration takes effect automatically without any reference in the child projects.

然而,我们可以在POM中的pluginManagement元素中明确声明和配置这些。主要的区别是,核心插件的配置会自动生效,不需要在子项目中进行任何引用

Let’s try this out by adding the compiler plugin to the familiar pluginManagement section:

让我们把compiler插件添加到熟悉的pluginManagement部分,来试试这个方法。

<pluginManagement>
    ....
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.10.0</version>
        <configuration>
            <source>1.8</source>
            <target>1.8</target>
        </configuration>
    </plugin>
    ....
</pluginManagement>

Here, we’ve locked down the plugin version and configured it to use Java 8 to build the project. However, there is no additional plugin declaration required in any child projects. The build framework activates this configuration by default. Therefore, this configuration means that the build must use Java 8 to compile this project across all modules.

在这里,我们已经锁定了插件的版本,并将其配置为使用Java 8来构建项目。然而,在任何子项目中都不需要额外的plugin声明。构建框架默认激活了这个配置。因此,这个配置意味着构建时必须使用Java 8来编译这个项目的所有模块。

Overall, it can be good practice to explicitly declare the configuration and lockdown the versions for any plugins required in a multi-module project. Consequently, different child projects can inherit only the required plugin configurations from the parent POM and apply them as needed.

总的来说,对于多模块项目中所需要的任何插件,明确声明其配置并锁定其版本,可以说是好的做法。因此,不同的子项目可以从父POM中只继承所需的插件配置,并根据需要应用它们。

This eliminates duplicate declarations, simplifies the POM files, and improves build reproducibility.

这消除了重复的声明,简化了POM文件,并提高了构建的可重复性。

6. Conclusion

6.结语

In this article, we’ve seen how to centralize and manage the Maven plugins required for building a project.

在本文中,我们已经看到了如何集中管理构建项目所需的Maven插件。

First, we looked at plugins and their usage in the project POM. Then we took a more detailed look at the Maven plugin management mechanism and how this helps to reduce duplication and improve the maintainability of the build configuration.

首先,我们研究了插件及其在项目POM中的使用。然后,我们更详细地了解了Maven的插件管理机制,以及它是如何帮助减少重复工作和提高构建配置的可维护性的。

As always, the example code is available over on GitHub.

像往常一样,示例代码可在GitHub上获得