写点什么

Maven 中的这些坑,99% 的人不知道!

  • 2025-07-29
    福建
  • 本文字数:2764 字

    阅读完需:约 9 分钟

前言

最近经常遇到知识星球中的小伙伴,问我一些关于 Maven 的问题。

说实话,Maven 在我们日常开发中,使用的频率非常高。

今天这篇文章跟大家总结一下,使用 Maven 时一些最常见的坑,希望对你会有所帮助。


1.Maven 核心原理

1.1 坐标体系



坐标冲突案例

<!-- 错误:同一artifactId声明两次 --><dependency>    <groupId>org.apache.httpcomponents</groupId>    <artifactId>httpclient</artifactId>    <version>4.5.13</version></dependency><dependency>    <groupId>com.aliyun</groupId>    <artifactId>httpclient</artifactId> <!-- 同名不同组! -->    <version>1.0.0</version></dependency>
复制代码


现象NoSuchMethodError 随机出现,因类加载器加载了错误 Jar


1.2 依赖传递


依赖解析流程:



传递规则

  1. 最短路径优先:A→B→C→D(1.0) vs A→E→D(2.0) → 选择 D(2.0)

  2. 第一声明优先:先声明的依赖版本胜出


1.3 生命周期



关键特性

  • 执行mvn install会自动触发从validateinstall的所有阶段

  • 插件绑定:每个阶段由具体插件实现(如compile阶段绑定maven-compiler-plugin


1.4 仓库体系



私服核心价值

  1. 缓存公共依赖 → 加速构建

  2. 托管内部二方包 → 安全隔离

  3. 控制依赖审批流 → 合规管控


2.Maven 中最常见的坑


坑 1:循环依赖

案例:订单模块order依赖支付模块payment,而payment又反向依赖order



报错[ERROR] A cycle was detected in the dependency graph

解决方案

  1. 抽取公共层:order-api ← order-core & payment-core

  2. 依赖倒置

// 在payment模块定义接口public interface PaymentService {    void pay(Order order); // 参数用Order接口}
// order模块实现接口public class OrderServiceImpl implements PaymentService { // 实现逻辑}
复制代码


坑 2:依赖冲突


典型场景:引入 A、B 两个组件

  • A 依赖 C:1.0

  • B 依赖 C:2.0

  • → Maven 按规则选择其一,导致另一方兼容性问题

定位工具

mvn dependency:tree -Dverbose
复制代码


输出:

[INFO] com.example:demo:jar:1.0[INFO] +- org.apache.httpcomponents:httpclient:jar:4.5.13:compile[INFO] |  \- commons-logging:commons-logging:jar:1.2:compile[INFO] \- com.aliyun:oss-sdk:jar:2.0.0:compile[INFO]    \- commons-logging:commons-logging:jar:1.1.3:compile (版本冲突)
复制代码


强制统一版本

<dependencyManagement>    <dependencies>        <dependency>            <groupId>commons-logging</groupId>            <artifactId>commons-logging</artifactId>            <version>1.2</version> <!-- 强制指定 -->        </dependency>    </dependencies></dependencyManagement>
复制代码


坑 3:快照依赖

错误配置

<dependency>    <groupId>com.internal</groupId>    <artifactId>core-utils</artifactId>    <version>1.0-SNAPSHOT</version> <!-- 快照版本! --></dependency>
复制代码


风险:相同版本号可能对应不同内容,导致生产环境行为不一致

规范

  1. 生产发布:必须使用RELEASE(如1.0.0

  2. 内部联调:使用SNAPSHOT但需配合持续集成


坑 4:依赖范围错误


误用案例

<dependency>    <groupId>javax.servlet</groupId>    <artifactId>javax.servlet-api</artifactId>    <version>4.0.1</version>    <scope>compile</scope> <!-- 应为provided --></dependency>
复制代码


后果:Tomcat 中运行时抛出java.lang.ClassCastException(容器已提供该包)

范围对照表



坑 5:资源过滤缺失

问题现象src/main/resources下的application.yml未替换变量:

db:  url: ${DB_URL}  # 未被替换!
复制代码


修复方案

<build>  <resources>    <resource>      <directory>src/main/resources</directory>      <filtering>true</filtering> <!-- 开启过滤 -->    </resource>  </resources></build>
复制代码


同时需在pom.xml中定义变量:

<properties>  <DB_URL>jdbc:mysql://localhost:3306/test</DB_URL></properties>
复制代码


坑 6:插件版本过时


经典案例:JDK 17+项目使用旧版编译器插件

<plugin>  <groupId>org.apache.maven.plugins</groupId>  <artifactId>maven-compiler-plugin</artifactId>  <version>3.1</version> <!-- 不支持JDK17 --></plugin>
复制代码


报错Fatal error compiling: invalid target release: 17

升级方案

<plugin>  <groupId>org.apache.maven.plugins</groupId>  <artifactId>maven-compiler-plugin</artifactId>  <version>3.11.0</version>  <configuration>    <source>17</source>    <target>17</target>  </configuration></plugin>
复制代码


坑 7:多模块构建顺序

错误结构

parent-pom  ├── user-service  ├── payment-service  # 依赖order-service  └── order-service
复制代码


构建命令mvn clean install → 可能先构建payment-service失败

正确配置

<!-- parent-pom中声明构建顺序 --><modules>  <module>order-service</module>  <module>payment-service</module> <!-- 确保顺序 -->  <module>user-service</module></modules>
复制代码


坑 8:本地仓库污染

故障场景mvn clean install成功,同事却失败根源:本地缓存了损坏的lastUpdated文件

清理方案

# 清除所有无效文件find ~/.m2 -name "*.lastUpdated" -exec rm {} \;
# 强制重新下载mvn clean install -U
复制代码


坑 9:私服配置错误


慢如蜗牛的原因

  1. 中央仓库直连(国内访问慢)

  2. 镜像配置错误


优化配置settings.xml):

<mirrors>  <mirror>    <id>aliyun</id>    <name>Aliyun Maven Mirror</name>    <url>https://maven.aliyun.com/repository/public</url>    <mirrorOf>central</mirrorOf> <!-- 覆盖中央仓库 -->  </mirror></mirrors>
复制代码


坑 10:IDE 与命令行行为不一致


典型分歧

  1. Eclipse 能编译,命令行失败 → .projectpom.xml不一致

  2. IDEA 运行正常,mvn test失败 → 测试资源未配置

统一方案

<!-- 显式配置测试资源 --><testResources>  <testResource>    <directory>src/test/resources</directory>    <filtering>true</filtering>  </testResource></testResources>
复制代码


3.企业级最佳实践


依赖管理黄金法则


1、严格父 POM:所有版本在父 POM 的<dependencyManagement>中锁定

2、持续检查:CI 流水线加入依赖检查

mvn versions:display-dependency-updates
复制代码

3、公私分明:公开依赖 → 从阿里云镜像下载内部依赖 → 私服管控


高可用构建架构



总结

  1. 能用:会执行mvn clean install

  2. 会用:理解生命周期、解决依赖冲突

  3. 善用:通过mvn dependency:analyze剔除无用依赖使用archetype生成标准化项目集成enforcer-plugin规范构建

Maven 的本质不是工具约束,而是架构纪律

当你不再被构建失败打断思绪,当你的依赖树如水晶般透明,才算真正驯服了这只“构建巨兽”。


文章转载自:苏三说技术

原文链接:https://www.cnblogs.com/12lisu/p/19004912

体验地址:http://www.jnpfsoft.com/?from=001YH


用户头像

还未添加个人签名 2023-06-19 加入

还未添加个人简介

评论

发布
暂无评论
Maven中的这些坑,99%的人不知道!_Java_不在线第一只蜗牛_InfoQ写作社区