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

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

    正在检查是否收录...
一言准备中...

前言

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

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

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

1.Maven核心原理

1.1 坐标体系

image

坐标冲突案例

<!-- 错误:同一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 依赖传递

依赖解析流程:

image

传递规则

  1. 最短路径优先

    :A→B→C→D(1.0) vs A→E→D(2.0) → 选择D(2.0)
  2. 第一声明优先

    :先声明的依赖版本胜出

1.3 生命周期

image

关键特性

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

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

1.4 仓库体系

image

私服核心价值

  1. 缓存公共依赖 → 加速构建
  2. 托管内部二方包 → 安全隔离
  3. 控制依赖审批流 → 合规管控

2.Maven中最常见的坑

坑1:循环依赖

案例

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

image

报错

[ERROR] A cycle was detected in the dependency graph

解决方案

  1. 抽取公共层:order-apiorder-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(容器已提供该包)

范围对照表

Scope 编译 测试 运行 典型用例
compile Spring Core
provided Servlet API
runtime JDBC驱动
test JUnit

坑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 
  1. 公私分明

    • 公开依赖 → 从阿里云镜像下载
    • 内部依赖 → 私服管控

高可用构建架构

image

总结

  1. 能用

    :会执行mvn clean install
  2. 会用

    :理解生命周期、解决依赖冲突
  3. 善用

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

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

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

最后说一句(求关注,别白嫖我)

如果这篇文章对您有所帮助,或者有所启发的话,帮忙关注一下我的同名公众号:苏三说技术,您的支持是我坚持写作最大的动力。

求一键三连:点赞、转发、在看。

关注公众号:【苏三说技术】,在公众号中回复:进大厂,可以免费获取我最近整理的10万字的面试宝典,好多小伙伴靠这个宝典拿到了多家大厂的offer。

本文收录于我的技术网站:http://www.susan.net.cn



  • 本文作者:WAP站长网
  • 本文链接: https://wapzz.net/post-27050.html
  • 版权声明:本博客所有文章除特别声明外,均默认采用 CC BY-NC-SA 4.0 许可协议。
本站部分内容来源于网络转载,仅供学习交流使用。如涉及版权问题,请及时联系我们,我们将第一时间处理。
文章很赞!支持一下吧 还没有人为TA充电
为TA充电
还没有人为TA充电
0
  • 支付宝打赏
    支付宝扫一扫
  • 微信打赏
    微信扫一扫
感谢支持
文章很赞!支持一下吧
关于作者
2.7W+
9
1
2
WAP站长官方

手把手教你多卡分布训练Accelerate使用配置教程

上一篇

源码浅析:SpringBoot main方法结束为什么程序不停止

下一篇
评论区
内容为空

这一切,似未曾拥有

  • 复制图片
按住ctrl可打开默认菜单