A Guide to Maven Artifact Classifiers – Maven Artifact分类器指南

最后修改: 2022年 2月 26日

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

1. Overview

1.概述

In this tutorial, we’ll be looking at the role of a Maven artifact classifier. Following that, we’ll take a look at the various scenarios where they might be useful. Before concluding, we’ll briefly discuss the Maven artifact type as well.

在本教程中,我们将了解Maven工件分类器的作用。随后,我们将看看它们可能有用的各种场景。在结束之前,我们还将简单讨论一下Maven工件的类型。

2. What Is a Maven Artifact Classifier?

2.什么是Maven工件分类器?

A Maven artifact classifier is an optional and arbitrary string that gets appended to the generated artifact’s name just after its version number. It distinguishes the artifacts built from the same POM but differing in content.

Maven工件分类器是一个可选的任意字符串,它被附加到生成的工件名称上,就在其版本号之后。它可以区分由同一POM构建但内容不同的工件。

Let’s consider the artifact definition:

让我们考虑文物的定义。

<groupId>com.baeldung</groupId>
<artifactId>maven-classifier-example-provider</artifactId>
<version>0.0.1-SNAPSHOT</version>

For this, the Maven jar plugin generates maven-classifier-example-provider-0.0.1-SNAPSHOT.jar.

为此,Maven jar插件生成了maven-classifier-example-provider-0.0.1-SNAPSHOT.jar

2.1. Generating Artifacts With a Classifier

2.1.用分类器生成工件

Let’s add a classifier configuration to the jar plugin:

让我们给jar插件添加一个分类器配置。

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>3.2.2</version>
            <executions>
                <execution>
                    <id>Arbitrary</id>
                    <goals>
                        <goal>jar</goal>
                    </goals>
                    <configuration>
                        <classifier>arbitrary</classifier>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

As a result, the maven-classifier-example-provider-0.0.1-SNAPSHOT-arbitrary.jar along with the maven-classifier-example-provider-0.0.1-SNAPSHOT.jar is generated.

因此,maven-classifier-example-provider-0.0.1-SNAPSHOT-arbitrary.jarmaven-classifier-example-provider-0.0.1-SNAPSHOT.jar一起被生成。

2.2. Consuming Artifacts With a Classifier

2.2.用分类器消耗工件

We’re now able to generate an artifact with a custom suffix using a classifier. Let’s see how we can use a classifier to consume the same.

我们现在能够使用分类器生成一个带有自定义后缀的工件。让我们看看我们如何使用分类器来消费同样的东西。

In order to consume the default artifact, we don’t have to do anything special:

为了消费默认的人工制品,我们不需要做任何特别的事情。

<dependency>
    <groupId>com.baeldung</groupId>
    <artifactId>maven-classifier-example-provider</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</dependency>

But, to consume the artifact with the custom suffix “arbitrary”, we’ll need to use the classifier element within the dependency element:

但是,为了消费带有自定义后缀 “arbitrary “的工件,我们需要在dependency元素中使用classifier元素。

<dependency>
    <groupId>com.baeldung</groupId>
    <artifactId>maven-classifier-example-provider</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <classifier>arbitrary</classifier>
</dependency>

After all this, a good question is why we would want to use a classifier? So, let’s look at some practical use cases where a classifier would be useful.

说了这么多,一个好问题是我们为什么要使用分类器?因此,让我们看看分类器有用的一些实际用例。

3. Using the Sources Classifier

3.使用来源分类器

We might have noticed that each Maven artifact is often accompanied by a “-sources.jar” artifact. It contains the source code, i.e., the .java files for the main artifact. It’s useful for debugging purposes.

我们可能已经注意到,每个Maven工件通常都有一个”-sources.jar”/em>工件。它包含源代码,即主要工件的.java文件。这对于调试来说是很有用的。

3.1. Generating Sources Artifact

3.1.生成源工件

Firstly, let’s generate a sources jar for the maven-classifier-example-provider module. We’ll use maven-source-plugin to do that:

首先,让我们为maven-classifier-example-provider模块生成一个源jar。我们将使用maven-source-plugin来完成这项工作。

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-source-plugin</artifactId>
    <version>3.2.1</version>
    <executions>
        <execution>
            <id>attach-sources</id>
            <phase>verify</phase>
            <goals>
                <goal>jar-no-fork</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Now, let’s run:

现在,我们来跑吧。

mvn clean install

As a result, the maven-classifier-example-provider-0.0.1-SNAPSHOT-sources.jar artifact is generated.

因此,生成了maven-classifier-example-provider-0.0.1-SNAPSHOT-sources.jar工件。

3.2. Consuming Sources Artifact

3.2.消耗源工件

Now, to consume the sources artifact, there are several ways. Let’s take a look at one of them. We can fetch sources jar for selective dependencies using a classifier element within the dependency definition:

现在,要使用Source工件,有几种方法。让我们来看看其中的一种。我们可以使用依赖性定义中的分类器元素来获取sources jar的选择性依赖性。

<dependency>
    <groupId>com.baeldung</groupId>
    <artifactId>maven-classifier-example-producer</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <classifier>sources</classifier>
</dependency>

Now, let’s run:

现在,我们来跑吧。

mvn clean install

As a result, the sources jar for this particular dependency is fetched. Generally, we don’t do this since it’ll unnecessarily pollute the POM. Hence, we usually prefer to use the capability of IDEs to attach the sources jar on-demand. Alternatively, we can also selectively fetch them via the mvn CLI command:

因此,这个特定依赖的源码罐被取走了。一般来说,我们不会这样做,因为这将不必要地污染POM。因此,我们通常倾向于使用IDE的功能来按需附加源代码jar。另外,我们也可以通过mvn CLI命令选择性地获取它们。

mvn dependency:sources -DincludeArtifactIds=maven-classifier-example-provider

In short, the key takeaway here is that the sources jar is referred to by using a sources classifier.

简而言之,这里的关键收获是,通过使用sources classifier来引用sources jar。

4. Using the Javadoc Classifier

4.使用Javadoc分类器

In the same vein as the sources jar use case, we’ve Javadoc. It contains the documentation for the main jar artifact.

与sources jar用例相同,我们有Javadoc。它包含了主要jar构件的文档。

4.1. Generating Javadoc Artifact

4.1.生成Javadoc工件

Let’s use the maven-javadoc-plugin to generate the Javadoc artifact:

让我们使用maven-javadoc-plugin来生成Javadoc工件。

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-javadoc-plugin</artifactId>
    <version>3.3.2</version>
    <executions>
        <execution>
            <id>attach-javadocs</id>
            <goals>
                <goal>jar</goal>
            </goals>
        </execution>
    </executions>
</plugin>

With the plugin defined, let’s run:

定义好插件后,我们开始运行。

mvn clean install

As a result, the maven-classifier-example-provider-0.0.1-SNAPSHOT-javadoc.jar artifact is generated.

因此,生成了maven-classifier-example-provider-0.0.1-SNAPSHOT-javadoc.jar artifact。

4.2. Consuming Javadoc Artifact

4.2.消耗Javadoc构件

Let’s now download the generated Javadoc from a consumer perspective via mvn:

现在让我们从消费者的角度通过mvn下载生成的Javadoc。

mvn dependency:resolve -Dclassifier=javadoc -DincludeArtifactIds=maven-classifier-example-provider

We can notice the -Dclassifier=javadoc option which specifies the classifier as javadoc.

我们可以注意到-Dclassifier=javadoc选项,它将分类器指定为javadoc

5. Using the Tests Classifier

5.使用测试分类器

Now, let’s look at a different use case that a classifier can serve. There might be various reasons we may want to get the tests jar of a module. For one, there could be certain test stubs that we might want to reuse. Let’s see how we can get the tests to jar independent of the main jar artifact via a classifier.

现在,让我们看一下分类器可以服务的不同用例。可能有各种原因,我们可能想得到一个模块的测试罐。首先,可能有一些测试存根,我们可能想重复使用。让我们看看我们如何通过分类器使测试独立于主jar artifact。

5.1. Generating Tests Jar

5.1.生成测试罐

Firstly, let’s generate the tests jar for the maven-classifier-example-provider module. In order to do that, we’ll use the Maven jar plugin by specifying test-jar goal:

首先,让我们为maven-classifier-example-provider模块生成测试jar。为了做到这一点,我们将通过指定test-jar目标来使用Maven的jar插件。

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <version>3.2.2</version>
    <executions>
        <execution>
            <id>Test Jar</id>
            <goals>
                <goal>test-jar</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Now, let’s run:

现在,我们来跑吧。

mvn clean install

As a result, the tests jar maven-classifier-example-provider-0.0.1-SNAPSHOT-tests.jar is generated and installed.

因此,测试jar maven-classifier-example-provider-0.0.1-SNAPSHOT-tests.jar被生成和安装。

5.2. Consuming Tests Jar

5.2.消耗测试罐

And now, let’s get the tests jar dependency into our consumer module maven-classifier-example-consumer. We do this using the tests classifier:

现在,让我们把测试的jar依赖关系引入消费者模块maven-classifier-example-consumer。我们使用tests分类器来实现这一目标。

<dependency>
    <groupId>com.baeldung</groupId>
    <artifactId>maven-classifier-example-provider</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <classifier>tests</classifier>
</dependency>

With that, we should be able to access the classes available in the test packages of maven-classifier-example-provider

有了这些,我们应该能够访问maven-classifier-example-provider的测试包中的可用类。

6. Using Classifiers to Support Multiple Java Versions

6.使用分类器来支持多个Java版本

Earlier, we had used an arbitrary classifier to build a second jar for our maven-classifier-example-provider module. Let’s now put that to more practical use.

早些时候,我们用一个任意的分类器为我们的maven-classifier-example-provider模块建立了第二个jar。现在让我们把它用于更实际的用途。

Java is now releasing a newer version at a much faster cadence of 6 months. Consequently, it requires the module developers to be able to support multiple versions of Java. It might sound like a challenging task to build multiple jars for our modules compiled with different Java versions. That’s where the Maven classifier comes to the rescue. We can build multiple jars compiled with different Java versions using a single POM.

Java现在以6个月的速度发布更新的版本。因此,它要求模块开发人员能够支持多个版本的Java。为使用不同Java版本编译的模块建立多个罐子,这听起来似乎是一项具有挑战性的任务。这时,Maven分类器就派上用场了。我们可以用一个POM构建用不同Java版本编译的多个jar。

6.1. Compiling With Multiple Java Versions

6.1.用多个Java版本进行编译

Firstly, we’ll configure the Maven compiler plugin to generate compiled class files using both JDK 8 and JDK 11:

首先,我们将配置Maven编译器插件,以便使用JDK 8和JDK 11生成编译后的类文件。

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.10.0</version>
    <executions>
        <execution>
            <id>JDK 8</id>
            <phase>compile</phase>
            <goals>
                <goal>compile</goal>
            </goals>
            <configuration>
                <source>8</source>
                <target>8</target>
                <fork>true</fork>
            </configuration>
        </execution>
        <execution>
            <id>JDK 11</id>
            <phase>compile</phase>
            <goals>
                <goal>compile</goal>
            </goals>
            <configuration>
                <outputDirectory>${project.build.outputDirectory}_jdk11</outputDirectory>
                <executable>${jdk.11.executable.path}</executable>
                <source>8</source>
                <target>11</target>
                <fork>true</fork>
            </configuration>
        </execution>
    </executions>
</plugin>

We’re setting up two execution blocks, one for Java 8 and the other for Java 11.

我们正在设置两个执行块,一个用于Java 8,另一个用于Java 11。

Following this, we’ve configured the outputDirectory to be different for Java 11. On the other hand, Java 8 compilation will use the default outputDirectory.

在这之后,我们将outputDirectory配置为与Java 11不同。另一方面,Java 8的编译将使用默认的outputDirectory

Next comes the source and target Java version configuration. The source code is written using Java 8, so we keep the source version as 8 and modify the target version for Java 11 execution block as 11.

接下来是源和目标Java版本的配置。源代码是用Java 8编写的,所以我们保持源版本为8,并将Java 11执行块的目标版本修改为11。

We’ve also explicitly provided the executable path for Java 11’s compiler javac. For Java 8, Maven will use the default javac configured on the system which in this case is Java 8’s javac:

我们还明确提供了Java 11的编译器javac的可执行路径。对于Java 8,Maven将使用系统上配置的默认javac,本例中就是Java 8的javac

mvn clean compile

As a result, two folders will be generated within the target folder – classes and classes_jdk11.

因此,在目标文件夹中会产生两个文件夹 – classesclasses_jdk11

6.2. Generating Jar Artifacts for Multiple Java Versions

6.2.为多个Java版本生成Jar构件

Secondly, we can proceed to package the module into two separate jars with the Maven jar plugin:

其次,我们可以用Maven jar插件将模块打包成两个独立的jar。

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <version>3.2.2</version>
    <executions>
        <execution>
            <id>default-package-jdk11</id>
            <phase>package</phase>
            <goals>
                <goal>jar</goal>
            </goals>
            <configuration>
                <classesDirectory>${project.build.outputDirectory}_jdk11</classesDirectory>
                <classifier>jdk11</classifier>
            </configuration>
        </execution>
    </executions>
</plugin>

We can notice that the classifier is set to jdk11.

我们可以注意到,分类器被设置为jdk11

Now, let’s run:

现在,我们来跑吧。

mvn clean install

As a result, two jars are generated – maven-classifier-example-provider-0.0.1-SNAPSHOT-jdk11.jar and maven-classifier-example-provider-0.0.1-SNAPSHOT.jar. The first one was compiled using the Java 11 compiler and the second using the Java 8 compiler.

因此,生成了两个jar–maven-classifier-example-provider-0.0.1-SNAPSHOT-jdk11.jarmaven-classifier-example-provider-0.0.1-SNAPSHOT.jar。第一个是用Java 11编译器编译的,第二个是用Java 8编译器编译的。

6.3. Consuming Jar Artifact of a Specific Java Version

6.3.消耗特定 Java 版本的 Jar Artifact

And finally, the consumers of our module can choose which jar artifact is relevant for them, based on the Java version they are using. Let’s see how we can use these jars from a consumer’s perspective.

最后,我们模块的消费者可以根据他们使用的Java版本,选择与他们有关的jar artifact。让我们从消费者的角度看看我们如何使用这些jar。

If we’re working on a Java 8 project we wouldn’t have to do anything special. We’ll just add a vanilla dependency:

如果我们在一个Java 8项目上工作,我们就不必做任何特别的事情。我们只需添加一个vanilla的依赖关系。

<dependency>
    <groupId>com.baeldung</groupId>
    <artifactId>maven-classifier-example-provider</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</dependency>

However, if we’re working on a Java 11 project we’ve to explicitly ask for the jar compiled with Java 11 via a classifier:

然而,如果我们正在处理一个Java 11项目,我们必须通过一个分类器明确要求使用Java 11编译的jar。

<dependency>
    <groupId>com.baeldung</groupId>
    <artifactId>maven-classifier-example-provider</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <classifier>jdk11</classifier>
</dependency>

7. Artifact Classifier vs. Artifact Type

7.工件分类器与工件类型

Before we conclude this article, let’s have a brief look at artifact type. While artifact type and classifier are closely related, they are not interchangeable. An artifact type defines the packing format of an artifact e.g. POM or jar. It also translates to the file extension in most cases. It may also have a corresponding classifier too.

在结束这篇文章之前,让我们简单看一下文物类型。虽然工件类型和分类器是密切相关的,但它们不能互换。一个工件类型定义了一个工件的打包格式,例如POM或者jar。在大多数情况下,它也被翻译成文件扩展名。它也可能有一个相应的分类器。

In other words, the artifact type deals with the packing of the artifact and may use a classifier to modify the name of the artifact generated.

换句话说,工件类型处理工件的包装,并可能使用分类器来修改生成的工件的名称。

The two use cases that we saw earlier with the Java Sources and the Javadoc are examples of artifact types that use sources and javadoc as classifiers.

我们之前看到的Java Sources和Javadoc的两个用例是使用sourcesjavadoc作为分类器的工件类型。

8. Conclusion

8.结语

In this article, we saw how classifiers provide a way to generate multiple artifacts from a single POM file. Using a classifier, the consumers can pick and choose from the various artifacts of a particular module as needed.

在这篇文章中,我们看到了分类器是如何提供一种从单个POM文件生成多个工件的方法。使用分类器,消费者可以根据需要从一个特定模块的各种工件中挑选。

As always, the code samples are available over on GitHub.

一如既往,代码样本可在GitHub上获得< data-saferedirecturl=”https://www.google.com/url?q=http://thelink.com/&source=gmail&ust=1640234878959000&usg=AOvVaw30romyOBJxqLz0Fo0Ry2P-” href=”https://github.com/eugenp/tutorials/tree/master/maven-modules/maven-classifier” rel=”noopener” target=”_blank”>over on Git。