不灭的焱

革命尚未成功,同志仍须努力 下载Java

作者:AlbertWen  添加时间:2026-02-15 12:55:51  修改时间:2026-02-15 16:52:39  分类:07.Java框架/系统  编辑

核心概念与区别

首先,我们先明确两者的本质定位,这是理解区别的关键:

特性 核心定位 解决的核心问题 作用阶段
Maven CI Friendly Versions Maven 原生特性(3.5.0+) 允许在 POM 中使用 ${revision}${sha1}${changelist} 等占位符定义版本,无需硬编码 构建时(Maven 解析 POM 阶段)
flatten-maven-plugin Maven 插件 解决 CI 友好版本占位符在发布时的 “污染” 问题(发布的 POM 不能包含占位符),同时可扁平化父子 POM 依赖 打包 / 发布阶段(generate-resources 或 package)

简单来说:

  • CI Friendly Versions 是 “允许你写占位符”,让版本管理更灵活;
  • flatten-maven-plugin 是 “清理占位符”,让发布的 POM 符合规范(纯静态版本)。

1. Maven CI Friendly Versions 示例

核心作用

在项目 POM 中用 ${revision} 统一管理版本,避免多模块项目中重复修改版本号。

示例(多模块项目)

父 POM (pom.xml)

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.example</groupId>
  <artifactId>parent-project</artifactId>
  <!-- 使用占位符代替硬编码版本 -->
  <version>${revision}</version>
  <packaging>pom</packaging>

  <!-- 定义版本占位符的默认值(可选) -->
  <properties>
    <revision>1.0.0-SNAPSHOT</revision>
  </properties>

  <modules>
    <module>module-a</module>
    <module>module-b</module>
  </modules>
</project>

子模块 POM (module-a/pom.xml)

<project>
  <parent>
    <groupId>com.example</groupId>
    <artifactId>parent-project</artifactId>
    <!-- 子模块直接继承父版本的占位符,无需改自己的版本 -->
    <version>${revision}</version>
  </parent>

  <artifactId>module-a</artifactId>
  <!-- 无需重复写 version,自动继承父版本 -->
</project>

使用方式

构建时通过命令行传入实际版本:

# 构建快照版本
mvn clean install -Drevision=1.0.0-SNAPSHOT

# 构建发布版本
mvn clean deploy -Drevision=1.0.0

问题点

如果直接用 mvn deploy 发布,发布到仓库的 POM 文件中依然会包含 ${revision} 占位符,其他项目依赖该模块时会解析失败 —— 这就是 flatten-maven-plugin 要解决的问题。

2. flatten-maven-plugin 示例

核心作用

将包含占位符的 “源 POM” 转换为 “扁平化 POM”(静态版本),并将扁平化后的 POM 发布到仓库。

示例(集成到父 POM)

修改上述父 POM,添加插件配置:

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.example</groupId>
  <artifactId>parent-project</artifactId>
  <version>${revision}</version>
  <packaging>pom</packaging>

  <properties>
    <revision>1.0.0-SNAPSHOT</revision>
  </properties>

  <build>
    <plugins>
      <!-- 配置 flatten 插件 -->
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>flatten-maven-plugin</artifactId>
        <version>1.5.0</version>
        <executions>
          <!-- 绑定到 generate-resources 阶段,生成扁平化 POM -->
          <execution>
            <id>flatten</id>
            <phase>generate-resources</phase>
            <goals>
              <goal>flatten</goal>
            </goals>
          </execution>
          <!-- 绑定到 clean 阶段,清理扁平化 POM -->
          <execution>
            <id>flatten.clean</id>
            <phase>clean</phase>
            <goals>
              <goal>clean</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <!-- 关键:使用 "resolveCiFriendliesOnly" 模式,只替换 CI 占位符 -->
          <flattenMode>resolveCiFriendliesOnly</flattenMode>
          <!-- 保留源 POM,将扁平化 POM 输出为 .flattened-pom.xml -->
          <updatePomFile>true</updatePomFile>
        </configuration>
      </plugin>
    </plugins>
  </build>

  <modules>
    <module>module-a</module>
    <module>module-b</module>
  </modules>
</project>

执行效果

  1. 执行 mvn clean install -Drevision=1.0.0 后,每个模块的 target 目录下会生成 .flattened-pom.xml
  2. 扁平化后的 POM 中,${revision} 会被替换为实际值 1.0.0
    <!-- module-a/target/.flattened-pom.xml -->
    <project>
      <parent>
        <groupId>com.example</groupId>
        <artifactId>parent-project</artifactId>
        <version>1.0.0</version> <!-- 占位符已替换 -->
      </parent>
      <artifactId>module-a</artifactId>
      <version>1.0.0</version> <!-- 自动填充实际版本 -->
    </project>
  3. 发布时,Maven 会将 .flattened-pom.xml 作为最终 POM 发布到仓库,其他项目依赖时能正常解析版本。 

总结

  1. 核心定位不同:CI Friendly Versions 是 Maven 原生的 “版本占位符机制”,解决版本统一管理问题;flatten-maven-plugin 是插件,解决占位符发布后无法解析的问题。
  2. 协作关系:两者通常配合使用 —— 先用 CI Friendly Versions 简化版本维护,再用 flatten-maven-plugin 清理占位符以符合发布规范。
  3. 关键区别:CI Friendly Versions 是 “写” 的层面的优化,flatten-maven-plugin 是 “发布” 层面的修正。

如果没有 CI Friendly Versions,你需要手动修改所有模块的版本号;如果只用 CI Friendly Versions 不用 flatten 插件,发布的 POM 会包含占位符导致依赖失败。