不止于仿真:用HFSS单元法分析矩形波导阵列的辐射方向图,从3D结果到实际工程意义解读
2026/6/13 6:13:05
在 Maven 多模块项目中,你可能会看到项目根目录和各个子模块下都存在一个.flattened-pom.xml文件,这个文件是做什么的?能删除吗?
这个问题涉及到 Maven 的一个核心矛盾:
开发时的灵活性 VS 发布时的兼容性 ↓ ↓ 使用变量、继承 需要具体值、独立性.flattened-pom.xml?.flattened-pom.xml是由Maven Flatten Plugin自动生成的扁平化 POM 文件。
简单类比:
=SUM(A1:A10))<!-- 👎 原始 pom.xml(开发时方便) --><groupId>org.gycoder</groupId><artifactId>smart-common</artifactId><version>${revision}</version><!-- 变量 --><properties><revision>1.0.0-SNAPSHOT</revision></properties>问题:当你把这个 JAR 发布到 Maven 中央仓库后,别人依赖你的项目时:
<!-- 其他开发者的项目 --><dependency><groupId>org.gycoder</groupId><artifactId>smart-common</artifactId><version>${revision}</version><!-- ❌ 别人的项目没有定义这个变量! --></dependency>Maven 报错:
Could not resolve dependencies: Failed to collect dependencies for org.gycoder:smart-common:jar:${revision}<!-- ✅ .flattened-pom.xml(发布时使用) --><groupId>org.gycoder</groupId><artifactId>smart-common</artifactId><version>1.0.0-SNAPSHOT</version><!-- 变量已被替换为具体值 -->现在别人就可以正常依赖了:
<dependency><groupId>org.gycoder</groupId><artifactId>smart-common</artifactId><version>1.0.0-SNAPSHOT</version><!-- ✅ 清晰明确 --></dependency><!-- pom.xml:187-212 --><plugin><groupId>org.codehaus.mojo</groupId><artifactId>flatten-maven-plugin</artifactId><version>1.7.2</version><configuration><!-- 只解析 CI Friendly 变量 --><flattenMode>resolveCiFriendliesOnly</flattenMode><!-- 更新 POM 文件(生成 .flattened-pom.xml) --><updatePomFile>true</updatePomFile></configuration><executions><!-- 在处理资源阶段生成扁平化 POM --><execution><id>flatten</id><phase>process-resources</phase><goals><goal>flatten</goal></goals></execution><!-- 在清理阶段删除扁平化 POM --><execution><id>flatten.clean</id><phase>clean</phase><goals><goal>clean</goal></goals></execution></executions></plugin>graph LR A[mvn install] --> B[process-resources 阶段] B --> C[flatten-maven-plugin 执行] C --> D[读取 pom.xml] D --> E[解析 ${revision} = 1.0.0-SNAPSHOT] E --> F[生成 .flattened-pom.xml] F --> G[后续构建使用扁平化 POM] H[mvn clean] --> I[clean 阶段] I --> J[flatten-maven-plugin clean] J --> K[删除 .flattened-pom.xml]| 原始 pom.xml | .flattened-pom.xml | 说明 |
|---|---|---|
<version>${revision}</version> | <version>1.0.0-SNAPSHOT</version> | 变量替换 |
<parent>...</parent> | (可能被移除或简化) | 继承展开 |
<properties>...</properties> | (可能被移除) | 属性内联化 |
<dependencyManagement> | (根据模式处理) | 依赖管理优化 |
<!-- pom.xml:10 --><version>${revision}</version><!-- pom.xml:31 --><properties><revision>1.0.0-SNAPSHOT</revision></properties>分析:
${revision}变量统一管理版本<!-- pom.xml:52-58 --><dependency><groupId>org.gycoder</groupId><artifactId>smart-dependencies</artifactId><version>${revision}</version><!-- 引用同一个变量 --><type>pom</type><scope>import</scope></dependency>分析:
<!-- 子模块 smart-common/pom.xml(假设) --><parent><groupId>org.gycoder</groupId><artifactId>smart-service-bot-parent</artifactId><version>${revision}</version><!-- 继承父版本 --></parent>分析:
# 1. 删除插件配置# 2. 执行构建mvn cleaninstall预期报错:
[ERROR] Failed to execute goal on project smart-common: Could not resolve dependencies for project org.gycoder:smart-common:jar:${revision}: Failed to collect dependencies at org.gycoder:smart-dependencies:pom:${revision}: Failed to read artifact descriptor for org.gycoder:smart-dependencies:pom:${revision}: Could not transfer artifact org.gycoder:smart-dependencies:pom:${revision} from/to central (https://repo.maven.apache.org/maven2): Illegal character in path at index 57: https://repo.maven.apache.org/maven2/org/gycoder/smart-dependencies/${revision}/...错误原因:
smart-dependencies:${revision}${revision}没有被解析,直接作为字符串使用${},导致失败项目结构: smart-service-bot-parent (1.0.0-SNAPSHOT) ├── smart-common (1.0.0-SNAPSHOT) ├── smart-auth (1.0.0-SNAPSHOT) ├── smart-api (1.0.1-SNAPSHOT) ← 版本不一致! └── ...问题:
<!-- 所有模块统一使用 --><version>${revision}</version><!-- 只需在父 POM 修改一处 --><properties><revision>2.0.0-RELEASE</revision><!-- 所有模块同步升级 --></properties>优势:
# GitLab CI 示例build:script:# 动态生成版本号:主版本.次版本.构建号-VERSION="2.0.${CI_PIPELINE_ID}"# 通过 -D 参数覆盖 revision 变量-mvn clean deploy-Drevision=${VERSION}# 发布到 Maven 仓库时,版本号为 2.0.1234对比传统方式:
# 传统方式:需要用 mvn versions 插件修改所有 pom.xmlmvn versions:set -DnewVersion=2.0.1234 mvn versions:commitgitadd.gitcommit -m"Bump version to 2.0.1234"# 然后才能构建mvn clean deploy1. Maven Reactor 构建顺序: smart-service-bot-parent ├── 解析 ${revision} = 1.0.0-SNAPSHOT(从当前 POM properties) ├── smart-common (version = ${revision}) │ └── Maven Reactor 知道 ${revision} = 1.0.0-SNAPSHOT └── smart-auth (version = ${revision}) └── 依赖 smart-common:${revision} └── Maven Reactor 在内存中已有 smart-common:1.0.0-SNAPSHOT 结论:本地多模块构建时,Maven Reactor 能正确解析 ${revision}1. smart-common 发布到 Maven 仓库: repo/org/gycoder/smart-common/ ├── 1.0.0-SNAPSHOT/ │ ├── smart-common-1.0.0-SNAPSHOT.jar │ └── smart-common-1.0.0-SNAPSHOT.pom ← 如果没有扁平化,包含 ${revision} 2. 其他项目依赖 smart-common: <dependency> <groupId>org.gycoder</groupId> <artifactId>smart-common</artifactId> <version>1.0.0-SNAPSHOT</version> </dependency> 3. Maven 下载并读取 POM: ❌ 如果 POM 中有 <version>${revision}</version> → Maven 无法解析(没有这个变量的定义) → 构建失败 ✅ 如果使用了 .flattened-pom.xml(已替换为具体值) → Maven 可以正确解析 → 构建成功<flattenMode>resolveCiFriendliesOnly</flattenMode>| flattenMode | 说明 | 适用场景 |
|---|---|---|
resolveCiFriendliesOnly | 只解析${revision},${sha1},${changelist}三个变量 | 推荐:你的项目使用此模式 |
oss | 更激进:移除<parent>、<properties>等 | 发布到 Maven Central |
bom | 仅保留<dependencyManagement> | BOM (Bill of Materials) 项目 |
fatJar | 为 fat JAR 优化 | Spring Boot 可执行 JAR |
defaults | 默认模式,平衡处理 | 一般项目 |
你的项目为什么选择resolveCiFriendliesOnly?
<!-- 原始 pom.xml --><parent>...</parent><!-- 保留:子模块需要知道父模块信息 --><properties><revision>1.0.0-SNAPSHOT</revision><!-- 仅解析这个 --><java.version>17</java.version><!-- 保留:其他属性不动 --></properties><!-- .flattened-pom.xml --><parent>...</parent><!-- ✅ 保留 --><version>1.0.0-SNAPSHOT</version><!-- ✅ ${revision} 被替换 --><properties><java.version>17</java.version><!-- ✅ 保留 --></properties># .gitignore.flattened-pom.xml **/.flattened-pom.xml原因:
.flattened-pom.xml是构建产物,不是源代码# .gitlab-ci.yml 示例variables:MAVEN_OPTS:"-Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository"build:stage:buildscript:-mvn clean install-Drevision=1.0.${CI_PIPELINE_ID}artifacts:paths:-target/*.jar# ❌ 不要包含 .flattened-pom.xml<!-- 开发分支 --><revision>1.0.0-SNAPSHOT</revision><!-- 发布候选 --><revision>1.0.0-RC1</revision><!-- 正式发布 --><revision>1.0.0</revision><!-- 紧急修复 --><revision>1.0.1-HOTFIX</revision>CI/CD 动态覆盖:
# 开发构建mvn cleaninstall-Drevision=1.0.0-DEV-${BUILD_NUMBER}# 生产发布mvn clean deploy -Drevision=1.0.0<!-- 父 POM --><revision>2.0.0</revision><!-- 所有子模块 -->smart-common:2.0.0 smart-auth:2.0.0 smart-api:2.0.0优点:
缺点:
<!-- 父 POM --><revision>1.0.0</revision><!-- 各模块独立定义 -->smart-common:1.0.0 smart-auth:1.2.0<!-- 认证模块有更新 -->smart-api:1.1.0<!-- API 有小改动 -->优点:
缺点:
${revision},失去 CI Friendly 优势建议:对于你的项目,使用策略 A(已采用)。
<plugin><groupId>org.codehaus.mojo</groupId><artifactId>flatten-maven-plugin</artifactId><version>1.7.2</version><configuration><!-- 只解析 CI Friendly 变量,保留其他配置 --><flattenMode>resolveCiFriendliesOnly</flattenMode><!-- 更新 POM 文件(生成 .flattened-pom.xml) --><updatePomFile>true</updatePomFile><!-- 扁平化后的依赖范围(可选) --><flattenDependencyMode>direct</flattenDependencyMode><!-- 输出目录(默认是项目根目录) --><outputDirectory>${project.build.directory}</outputDirectory></configuration><executions><!-- 构建时生成 --><execution><id>flatten</id><phase>process-resources</phase><goals><goal>flatten</goal></goals></execution><!-- 清理时删除 --><execution><id>flatten.clean</id><phase>clean</phase><goals><goal>clean</goal></goals></execution></executions></plugin>.flattened-pom.xml❌ 错误做法:
# 手动修改 .flattened-pom.xmlvim.flattened-pom.xml✅ 正确做法:
pom.xml,插件会自动重新生成原因:
.flattened-pom.xml提交到 Git❌ 错误做法:
gitadd.flattened-pom.xmlgitcommit -m"Add flattened pom"✅ 正确做法:
# .gitignore.flattened-pom.xml **/.flattened-pom.xml原因:
场景:
<!-- 删除 flatten-maven-plugin 配置 --><!-- 但保留 ${revision} 变量 -->结果:
mvn cleaninstall# ❌ 构建失败!教训:
${revision}等 CI Friendly 变量错误示例:
<!-- ❌ 错误:对于多模块项目使用 oss 模式 --><flattenMode>oss</flattenMode>后果:
<!-- .flattened-pom.xml --><!-- ❌ <parent> 被移除,子模块无法识别父模块 --><!-- ❌ <properties> 全部被移除,丢失重要配置 -->正确做法:
<!-- ✅ 多模块项目推荐 --><flattenMode>resolveCiFriendliesOnly</flattenMode>场景:
# 本地构建成功mvn cleaninstall# ✅ 成功!# 发布到 Maven 仓库mvn clean deploy# ✅ 成功!# 其他项目依赖<dependency><groupId>org.gycoder</groupId><artifactId>smart-common</artifactId><version>1.0.0-SNAPSHOT</version></dependency># ❌ 失败!(如果没有使用 flatten)原因:
${revision}教训:
| 特性 | 不使用 flatten-maven-plugin | 使用 flatten-maven-plugin |
|---|---|---|
| 版本号定义 | <version>1.0.0-SNAPSHOT</version> | <version>${revision}</version> |
| 版本修改 | 需手动修改每个模块 | 只需修改一处<revision> |
| CI/CD 动态版本 | 需要使用versions:set插件 | 通过-Drevision=xxx参数 |
| 本地构建 | ✅ 正常 | ✅ 正常 |
| 发布到仓库 | ✅ 正常 | ✅ 正常(使用扁平化 POM) |
| 其他项目依赖 | ✅ 正常 | ✅ 正常(变量已被替换) |
| 版本一致性 | ❌ 容易不一致 | ✅ 强制一致 |
| Yudao 技术栈对齐 | ❌ 不符合 | ✅ 符合最佳实践 |
.flattened-pom.xml是什么?
为什么需要它?
你的项目必须使用它
${revision}变量| 操作 | 建议 | 原因 |
|---|---|---|
| 删除 .flattened-pom.xml | ❌ 不要手动删除 | 会自动重新生成 |
| 编辑 .flattened-pom.xml | ❌ 永远不要编辑 | 构建时会覆盖 |
| 提交到 Git | ❌ 添加到 .gitignore | 这是构建产物 |
| 删除 flatten-maven-plugin | ❌ 必须保留 | 项目依赖此插件 |
| 修改 flattenMode | ⚠️ 保持 resolveCiFriendliesOnly | 适合你的项目 |
Maven 依赖解析的本质问题: 本地构建 远程依赖 ↓ ↓ Maven Reactor 独立 POM 文件 (内存管理) (文件读取) ↓ ↓ 可解析 ${revision} 无法解析 ${revision} ↓ ↓ 构建成功 ✅ 构建失败 ❌ 解决方案:flatten-maven-plugin 原始 pom.xml .flattened-pom.xml ↓ ↓ ${revision} 变量 1.0.0-SNAPSHOT 具体值 ↓ ↓ 本地开发使用 发布到仓库使用