Maven实战进阶(01)面试官:Maven怎么解决依赖冲突?| 有几种解决方式

简介: 本文介绍了Maven的核心功能和依赖管理技巧。Maven是基于项目对象模型(POM)的构建工具,具备跨平台、标准化、自动化等特性。其三大核心功能为依赖管理、仓库管理和项目构建。依赖管理通过pom.xml文件引入第三方组件并自动下载;仓库管理涉及中央仓库、私服和本地仓库;项目构建则通过生命周期管理编译、测试、打包等流程。文章还详细讲解了依赖冲突的解决方法,包括默认规则、手工排除和版本指定等策略。

读书笔记:给负面情绪降温,再寻求解决冲突问题。常见负面情绪有愤怒、悲伤、恐惧三大类。细分有生气、不满、伤心、担忧、缺少安全感等。识别自己的情绪、中性表达你所听到、看到的事实,不主观臆测,准确表达自己的情绪。此外,也需要疏导对方情绪,最后达成情绪共鸣,再寻求化解分歧和误会,找到解决方案。


一、前言背景

二、Maven是什么?

2.1 三大常用核心功能之依赖管理

2.2 三大常用核心功能之仓库管理

2.3 三大常用核心功能之项目构建

三、依赖是什么?从哪来?放哪里?

3.1 依赖里的scope是什么,有什么用?

3.2 依赖不在Maven仓库,怎么办?

四、如何解决依赖冲突?

4.1 Maven默认的解决方式

4.2 手工解决方式

4.3 其他方式


一、前言背景

    Maven是什么?在很多初中级研发印象里,Maven只是系统项目里的一个pom.xml文件,甚至连mvn clean package命令都逐渐模糊。而项目研发技术leader、架构师已经把依赖管理、插件配置、整个系统的devops管理都做好了。大部分时间,大家只需要专注迭代完成系统业务功能开发。

    然而,所有能被广泛应用的技术组件,背后必有超凡的设计和值得深入探索的技术价值。如果时间允许+自己也有兴趣,可以深入理解它的核心原理以及高阶特性。这个对我们研发技术经验积累和架构设计能力提升有极大帮助。

    知识传播分享,不分高下,各有千秋。最近喜欢以专栏的形式,持续连载分享某个框架原理,也是希望能和有缘刷到且有兴趣的朋友,一起深入交流学习分享。也希望未来可以轻松的写一点新版本特性、或者只针对某个技术要点、生产故障进行详细探讨。

    话不多说,今天正式开始我们的《Maven实战进阶系列》之旅。保持一贯风格,行文尽可能通俗易懂、图文并茂,以核心架构原理开局,力争以实战demo进阶,最后愿我们学海无涯,所见皆有所获。


二、Maven是什么?

    Apache Maven是基于项目对象模型(POM)概念的项目管理构建工具。具有跨平台、标准化、自动化等特性。对于我们日常项目研发来说,Maven就是一个通过pom.xml文件来管理我们依赖包、插件、项目基础信息、项目构建的一个高度标准自动化的管理平台。

    如果要说说Maven三大最常用、最核心的功能,我选择依赖管理、仓库管理、项目构建。


2.1 三大常用核心功能之依赖管理

     首先,依赖管理,就是我们在pom里进行的项目依赖包的管理。我们只需要将依赖的第三方组件信息,通过dependency进行引入,maven就自动帮我们下载对应包以及管理它的生命周期。



2.2 三大常用核心功能之仓库管理

     maven仓库有三种,一个是maven的中央仓库、一个是私服、一个是本地仓库。


     在我们安装好maven后,本地有个仓库。比如我maven安装目录是:/Users/xxxx/soft/maven3.6.3。在该目录下,有个.m2目录,里面的repository文件夹,就是本地仓库。


     查看本地仓库依赖包信息:ls .m2/repository

     第二个私服。在企业里,公司需要搭建一个私有的公共maven仓库,方便存放管理内部各个研发项目的版本。此外,maven的中央仓库,由于是部署在国外,国内访问速度慢且网络不稳定。私服的存在,可以作为一个依赖缓存,避免研发依赖引入出现重复下载。

     第三个,maven官方中央仓库https://mvnrepository.com/。这里存放共享着maven社区众多主流开源组件。基本上我们想要的依赖,在中央仓库都能找到。

     此外,有些小公司,或者不需要搭建maven私服的企业,可以让研发人员配置国内主流远程仓库,比如阿里、清华仓库源,下载速度都非常快。

在.m2/settings.xml文件配置:


<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
                          https://maven.apache.org/xsd/settings-1.0.0.xsd">
      
      <mirrors>
      <mirror>  
          <id>alimaven</id>  
          <name>aliyun maven</name>  
          <url>http://maven.aliyun.com/nexus/content/groups/public/</url>  
          <mirrorOf>central</mirrorOf>          
      </mirror>  
      </mirrors>
</settings>


2.3 三大常用核心功能之项目构建

    日常项目构建,从代码编写就已经开始,写代码引入的包类需要maven管理构建引入,此后代码编译测试、运行、打包等过程都是项目构建流程内容。

    在maven里,项目构建和生命周期密切相关。甚至就是maven通过生命周期来统一管理项目的构建过程。可以说项目构建管理,就是maven的生命周期管理。生命周期包括:清理、编译、测试、打包、部署、发布等过程。应用也非常简单,直接是mvn 后加生命周期名字即可,比如:mvn clean package。

   这块内容会非常多,开篇我们简单了解即可,后续出一篇文章专门讲生命周期这块。



三、依赖是什么?从哪来?放哪里?

    依赖就是我们系统项目依赖的第三方组件,比如fastjson、commons-langs组件。


    在2.1我们也说过,在pom里  的 进行引入。这些依赖包,maven首先会从本地.m2仓库查找,如果没有找到,就从配置的远程仓库里找,一般是公司私服。如果公司私服也没有,私服就从远程仓库里下载。下载之后,存放在本地仓库。


3.1 依赖里的scope是什么,有什么用?

    依赖里,除了groupId,artifactId,version,还有一个scope标签。比如我们日常用来做测试用的junit、Springboot test插件:


<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <scope>test</scope>
    <version>3.8.2</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

    这个scope标签,就是我们依赖包使用范围。它有6个范围:compile、provided、runtime、test、system、import。用的最多默认值complie。

    如果scope是complie,那依赖包可以使用范围最广,从编译、测试、运行均会被应用。

    而test,就是在我们test代码里可以使用。如果尝试在主代码main里使用scope为test的依赖,就会报错。

   这块很有意思,如果时间允许,可以自己实践改不同scope去测试验证。

   对我们来说,如果使用不多,其实这块不需要太关注,因为在我们去中央仓库查找时候,官方已经给了推荐默认值,我们直接使用即可。


3.2 依赖不在Maven仓库,怎么办?

    现实里,有些特殊依赖包,并没有共享上传到maven的中央仓库、而且公司私服也没有。这种包,我们可以通过打包上传到私服。然后再在项目里引用。如果仅仅是本地使用,可以直接放到自己电脑Maven本地仓库。


四、如何解决依赖冲突?

   在maven依赖管理里,什么是依赖冲突?

   这个是初级开发、尤其是校招生面试的时候,经常被问到的基础问题。以及刚才所探讨的几个小问题。

   依赖冲突,实际是多个组件依赖的同一个第三方组件,但是版本不一致问题。比如,项目引入了pring-boot-starter-log4j2、以及commons-logging组件,但是两者底层都依赖了log4j-core,且版本不一致:

spring-boot-starter-log4j2 ,依赖log4j-core 版本2.23.1。

commons-logging 也依赖了log4j-core ,但是版本2.24.3。

4.1 Maven默认的解决方式

   Maven对依赖冲突解决很简单:依赖版本不一致,就进行N选1(gradle更简单,直接是取最新版本为准)。不过这个N选1,maven有2个原则:

    第一声明优先原则。在pom文件里,哪个依赖所处位置更靠前,就是优先声明,默认被引入进来。后续的冲突依赖,就不会被依赖进来(除非手工解决干预)。

   路径最近优先原则。依赖是有传递性的,比如项目直接依赖了A组件V1.0、B组件。而B组件依赖了A组件的V2.0。由于V1.0的A组件,是被项目直接引入,那A组件的V1.0被引入。冲突的V2.0不会被引入。

4.2 手工解决方式

    对于冲突依赖,maven支持手工依赖排除,通过exclusion标签去设置。比如:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
    <exclusions>
        <exclusion>
            <artifactId>accessors-smart</artifactId>
            <groupId>net.minidev</groupId>
        </exclusion>
    </exclusions>
</dependency>

    此外,手工指定版本。有点类似4.1说的路径最近优先原则。比如项目直接引入依赖A、B组件。而A和B分别依赖C的V1和V2版本。这时候我们可以直接在项目里引入C组件,并指定对应版本来解决冲突。


4.3 其他方式

    比如我们内部自研基础组件项目服务A依赖是pinyin4j。当我们打包服务A给其他项目使用,避免依赖pinyin4j给其他服务造成影响,我们设置pinyin4j的依赖进行依赖阻断。依赖阻断就是通过 设置为true来实现。比如:

<dependency>
    <groupId>com.belerweb</groupId>
    <artifactId>pinyin4j</artifactId>
    <version>2.5.1</version>
    <optional>true</optional>
</dependency>

    这样就可以避免其他服务在应用我们的基础组件时,需要手工解决依赖冲突问题。


推荐阅读拉丁解牛相关专题系列(欢迎交流讨论):

1、JVM进阶调优系列(3)堆内存的对象什么时候被回收?

2、JVM进阶调优系列(2)字节面试:JVM内存区域怎么划分,分别有什么用?

3、JVM进阶调优系列(1)类加载器原理一文讲透

4、JAVA并发编程系列(13)Future、FutureTask异步小王子

5、MySQL进阶突击系列(05)突击MVCC核心原理 | 左右护法ReadView视图和undoLog版本链强强联合

相关文章
|
4月前
|
缓存 Java API
Java 面试实操指南与最新技术结合的实战攻略
本指南涵盖Java 17+新特性、Spring Boot 3微服务、响应式编程、容器化部署与数据缓存实操,结合代码案例解析高频面试技术点,助你掌握最新Java技术栈,提升实战能力,轻松应对Java中高级岗位面试。
414 0
|
8月前
|
Java Maven 微服务
微服务——SpringBoot使用归纳——Spring Boot集成 Swagger2 展现在线接口文档——Swagger2 的 maven 依赖
在项目中使用Swagger2工具时,需导入Maven依赖。尽管官方最高版本为2.8.0,但其展示效果不够理想且稳定性欠佳。实际开发中常用2.2.2版本,因其稳定且界面友好。以下是围绕2.2.2版本的Maven依赖配置,包括`springfox-swagger2`和`springfox-swagger-ui`两个模块。
295 0
|
5月前
|
NoSQL Java 微服务
2025 年最新 Java 面试从基础到微服务实战指南全解析
《Java面试实战指南:高并发与微服务架构解析》 本文针对Java开发者提供2025版面试技术要点,涵盖高并发电商系统设计、微服务架构实现及性能优化方案。核心内容包括:1)基于Spring Cloud和云原生技术的系统架构设计;2)JWT认证、Seata分布式事务等核心模块代码实现;3)数据库查询优化与高并发处理方案,响应时间从500ms优化至80ms;4)微服务调用可靠性保障方案。文章通过实战案例展现Java最新技术栈(Java 17/Spring Boot 3.2)的应用.
367 9
|
5月前
|
缓存 算法 NoSQL
校招 Java 面试高频常见知识点深度解析与实战案例详细分享
《2025校招Java面试核心指南》总结了Java技术栈的最新考点,涵盖基础语法、并发编程和云原生技术三大维度: 现代Java特性:重点解析Java 17密封类、Record类型及响应式Stream API,通过电商案例演示函数式数据处理 并发革命:对比传统线程池与Java 21虚拟线程,详解Reactor模式在秒杀系统中的应用及背压机制 云原生实践:提供Spring Boot容器化部署方案,分析Spring WebFlux响应式编程和Redis Cluster缓存策略。
140 0
|
5月前
|
缓存 NoSQL Java
校招 Java 面试常见知识点及实战案例全解析
本文全面解析了Java校招面试中的常见知识点,涵盖Java新特性(如Lambda表达式、、Optional类)、集合框架高级应用(线程安全集合、Map性能优化)、多线程与并发编程(线程池配置)、JVM性能调优(内存溢出排查、垃圾回收器选择)、Spring与微服务实战(Spring Boot自动配置)、数据库与ORM框架(MyBatis高级用法、索引优化)、分布式系统(分布式事务、缓存应用)、性能优化(接口优化、高并发限流)、单元测试与代码质量(JUnit 5、Mockito、JaCoCo)以及项目实战案例(电商秒杀系统、社交消息推送)。资源地址: [https://pan.quark.cn/s
185 4
|
7月前
|
存储 Java Maven
Maven系统级别依赖:解决部署时Jar包缺失问题
以上就是关于Maven系统级别依赖解决部署时Jar包缺失问题的解答,希望对你有所帮助。在软件开发中,遇到问题并解决问题是常态,希望你能够善用这些工具,解决你遇到的问题。
438 28
|
11月前
|
缓存 Java Maven
【简单四步教你解决♥十分有效】Maven依赖报错、依赖或插件导入失败的万能解决办法
【简单四步教你解决♥十分有效】Maven依赖报错、依赖或插件导入失败的万能解决办法!在处理Maven项目问题时,首先检查Maven配置是否正确。接着通过“File--Invalidata Caches”清除IDEA缓存并重启。使用Maven命令`mvn dependency:purge-local-repository`和`mvn dependency:resolve`清除本地依赖缓存。最后,在Terminal中输入`mvn clean install`完成构建。
3185 1
【简单四步教你解决♥十分有效】Maven依赖报错、依赖或插件导入失败的万能解决办法
|
11月前
|
并行计算 算法 安全
面试必问的多线程优化技巧与实战
多线程编程是现代软件开发中不可或缺的一部分,特别是在处理高并发场景和优化程序性能时。作为Java开发者,掌握多线程优化技巧不仅能够提升程序的执行效率,还能在面试中脱颖而出。本文将从多线程基础、线程与进程的区别、多线程的优势出发,深入探讨如何避免死锁与竞态条件、线程间的通信机制、线程池的使用优势、线程优化算法与数据结构的选择,以及硬件加速技术。通过多个Java示例,我们将揭示这些技术的底层原理与实现方法。
621 3
|
Java Maven
maven打瘦包,且只打入部分想打入的依赖瘦包
maven打瘦包,且只打入部分想打入的依赖瘦包 设计 工程结构分析 环境管理 城市资源 安全工程 工程管理
242 10

推荐镜像

更多