2. 什么是 Maven Artifact Classifier?

Maven Artifact Classifier 是一个可选的任意字符串,它会被附加到生成构件的名称中,紧跟在版本号之后。它的作用是区分那些来自同一 POM 但内容不同的构件。

考虑这个构件定义:

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

Maven jar 插件会生成 maven-classifier-example-provider-0.0.1-SNAPSHOT.jar

2.1. 使用 Classifier 生成构件

给 jar 插件添加 classifier 配置:

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

执行后会生成两个文件:

  • maven-classifier-example-provider-0.0.1-SNAPSHOT.jar
  • maven-classifier-example-provider-0.0.1-SNAPSHOT-arbitrary.jar

2.2. 使用 Classifier 消费构件

消费默认构件无需特殊处理:

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

但消费带 "arbitrary" 后缀的构件时,需要在依赖中添加 <classifier>

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

为什么需要 classifier? 接下来看几个实用场景。

3. 使用 Sources Classifier

你可能注意到每个 Maven 构件常伴随一个 *-sources.jar 文件。它包含主构件的源码(.java 文件),对调试很有帮助。

3.1. 生成 Sources 构件

使用 maven-source-plugin 为模块生成 sources jar:

<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>

执行 mvn clean install 后生成: maven-classifier-example-provider-0.0.1-SNAPSHOT-sources.jar

3.2. 消费 Sources 构件

消费 sources jar 有多种方式。在依赖中显式指定:

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

但通常不推荐这样做(会污染 POM)。更常见的做法:

  • 让 IDE 按需附加源码
  • 通过 Maven 命令选择性下载:
    mvn dependency:sources -DincludeArtifactIds=maven-classifier-example-provider
    

核心要点:sources jar 通过 sources classifier 引用。

4. 使用 Javadoc Classifier

类似 sources jar,javadoc jar 包含主构件的 API 文档。

4.1. 生成 Javadoc 构件

使用 maven-javadoc-plugin

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

执行 mvn clean install 后生成: maven-classifier-example-provider-0.0.1-SNAPSHOT-javadoc.jar

4.2. 消费 Javadoc 构件

通过 Maven 命令下载 javadoc:

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

注意 -Dclassifier=javadoc 参数指定了 classifier。

5. 使用 Tests Classifier

现在看另一个实用场景:获取模块的测试 jar。比如想复用测试桩代码。

5.1. 生成 Tests Jar

使用 Maven jar 插件的 test-jar 目标:

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

执行 mvn clean install 后生成: maven-classifier-example-provider-0.0.1-SNAPSHOT-tests.jar

5.2. 消费 Tests Jar

在消费者模块中通过 tests classifier 引入:

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

这样就能访问 maven-classifier-example-provider 的测试包中的类了。

6. 使用 Classifier 支持多 Java 版本

Java 版本更新加速(6个月一版),模块开发者需要支持多个版本。用 classifier 可以轻松构建不同版本编译的 jar。

6.1. 多版本编译

配置 Maven 编译插件同时生成 JDK 8 和 JDK 11 的字节码:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.12.1</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>

关键配置:

  • Java 8 使用默认输出目录
  • Java 11 输出到 classes_jdk11 目录
  • 源码兼容 Java 8,但 Java 11 目标版本为 11

执行 mvn clean compile 后生成:

  • target/classes (Java 8 编译)
  • target/classes_jdk11 (Java 11 编译)

6.2. 生成多版本 Jar 构件

用 Maven jar 插件打包:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <version>3.3.0</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>

**注意 classifier 设置为 jdk11**。

执行 mvn clean install 后生成:

  • maven-classifier-example-provider-0.0.1-SNAPSHOT.jar (Java 8 编译)
  • maven-classifier-example-provider-0.0.1-SNAPSHOT-jdk11.jar (Java 11 编译)

6.3. 消费特定版本 Jar

消费者根据自身 Java 版本选择构件:

  • Java 8 项目(默认):
    <dependency>
        <groupId>com.baeldung</groupId>
        <artifactId>maven-classifier-example-provider</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>
    
  • Java 11 项目:
    <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

artifact type 和 classifier 密切相关但不可互换:

  • Type 定义构件的打包格式(如 POM、jar),通常对应文件扩展名
  • Classifier 用于修改构件名称,区分内容差异

官方文档说明:artifact type 处理构件打包,可能使用 classifier 修改生成名称。

典型例子:

  • sourcesjavadoc 是 classifier,但它们对应的 type 仍是 jar

8. 总结

本文展示了如何通过 classifier 从单个 POM 生成多个构件。消费者可以根据需要选择模块的不同变体。

核心优势

  • 简单粗暴解决多版本兼容问题
  • 灵活分离源码/文档/测试代码
  • 避免重复创建模块

代码示例已上传至 GitHub


原始标题:A Guide to Maven Artifact Classifiers | Baeldung