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 修改生成名称。
典型例子:
sources
和javadoc
是 classifier,但它们对应的 type 仍是jar
8. 总结
本文展示了如何通过 classifier 从单个 POM 生成多个构件。消费者可以根据需要选择模块的不同变体。
核心优势:
- 简单粗暴解决多版本兼容问题
- 灵活分离源码/文档/测试代码
- 避免重复创建模块
代码示例已上传至 GitHub