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

本文涉及的产品
云原生网关 MSE Higress,422元/月
注册配置 MSE Nacos/ZooKeeper,118元/月
任务调度 XXL-JOB 版免费试用,400 元额度,开发版规格
简介: 本文介绍了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版本链强强联合

目录
打赏
0
14
14
1
95
分享
相关文章
【简单四步教你解决♥十分有效】Maven依赖报错、依赖或插件导入失败的万能解决办法
【简单四步教你解决♥十分有效】Maven依赖报错、依赖或插件导入失败的万能解决办法!在处理Maven项目问题时,首先检查Maven配置是否正确。接着通过“File--Invalidata Caches”清除IDEA缓存并重启。使用Maven命令`mvn dependency:purge-local-repository`和`mvn dependency:resolve`清除本地依赖缓存。最后,在Terminal中输入`mvn clean install`完成构建。
【简单四步教你解决♥十分有效】Maven依赖报错、依赖或插件导入失败的万能解决办法
面试必问的多线程优化技巧与实战
多线程编程是现代软件开发中不可或缺的一部分,特别是在处理高并发场景和优化程序性能时。作为Java开发者,掌握多线程优化技巧不仅能够提升程序的执行效率,还能在面试中脱颖而出。本文将从多线程基础、线程与进程的区别、多线程的优势出发,深入探讨如何避免死锁与竞态条件、线程间的通信机制、线程池的使用优势、线程优化算法与数据结构的选择,以及硬件加速技术。通过多个Java示例,我们将揭示这些技术的底层原理与实现方法。
95 3
|
2月前
|
maven打瘦包,且只打入部分想打入的依赖瘦包
maven打瘦包,且只打入部分想打入的依赖瘦包 设计 工程结构分析 环境管理 城市资源 安全工程 工程管理
83 10
除了 Maven,还有哪些工具可以管理项目的依赖和版本冲突
除了Maven,常用的项目依赖管理和版本冲突解决工具有Gradle、Ivy、Ant+Ivy、SBT等。这些工具各有特点,适用于不同的开发环境和需求。
276 2
|
3月前
|
【Maven】依赖管理,Maven仓库,Maven核心功能
【Maven】依赖管理,Maven仓库,Maven核心功能
879 3
|
3月前
|
Maven 依赖管理
Maven 一个核心的特性就是依赖管理。当我们处理多模块的项目(包含成百上千个模块或者子项目),模块间的依赖关系就变得非常复杂,管理也变得很困难。针对此种情形,Maven 提供了一种高度控制的方法。
189 5
|
4月前
|
Maven 引入外部依赖
如果我们需要引入第三方库文件到项目,该怎么操作呢?
62 5
三个小时vue3.x从零到实战(vue3.x面试总结)
该文章总结了Vue 3.x面试中常见的知识点和问题,包括Vue的生命周期、核心概念、组件通信方式等方面的内容,有助于准备Vue相关技术面试。
61 0
|
2月前
|
从零开始学 Maven:简化 Java 项目的构建与管理
Maven 是一个由 Apache 软件基金会开发的项目管理和构建自动化工具。它主要用在 Java 项目中,但也可以用于其他类型的项目。
91 1
从零开始学 Maven:简化 Java 项目的构建与管理
|
2月前
|
maven项目的pom.xml文件常用标签使用介绍
第四届人文,智慧教育与服务管理国际学术会议(HWESM 2025) 2025 4th International Conference on Humanities, Wisdom Education and Service Management
261 8
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等