Maven 依赖管理基础(二)

news/2025/2/25 13:41:50

四、Maven 依赖管理实战演练

4.1 创建 Maven 项目

我们可以使用 Maven 命令行工具或集成开发环境(IDE)来创建 Maven 项目,这里以 IntelliJ IDEA 为例进行演示。

首先,打开 IntelliJ IDEA,点击 “Create New Project” 创建新项目。在弹出的窗口中,左侧选择 “Maven”,确保勾选了 “Create from archetype”,这样可以从模板创建项目,方便快捷。在模板列表中,我们选择 “maven-archetype-quickstart”,这是一个简单的 Java 项目模板,适合初学者快速上手,然后点击 “Next”。

接下来,设置项目坐标。在 “GroupId” 中填写项目的组织标识符,一般采用反向域名的形式,比如 “com.example”;在 “ArtifactId” 中填写项目名称,例如 “my - maven - project”;“Version” 则是项目的版本号,这里我们填写 “1.0 - SNAPSHOT”,“SNAPSHOT” 表示这是一个开发中的版本,会随着开发不断更新。填写完成后,点击 “Next”。

最后,选择项目的存储位置,点击 “Finish”,一个 Maven 项目就创建成功了。

使用命令行创建 Maven 项目也很简单,打开命令行工具,进入你希望创建项目的目录,然后执行以下命令:

 

mvn archetype:generate -DgroupId=com.example -DartifactId=my - maven - project -DarchetypeArtifactId=maven - archetype - quickstart -DinteractiveMode=false

这个命令中,archetype:generate表示使用 Maven 原型插件来生成项目结构;-DgroupId=com.example设置项目的组织标识符;-DartifactId=my - maven - project设置项目的名称;-DarchetypeArtifactId=maven - archetype - quickstart指定使用的原型为简单 Java 项目模板;-DinteractiveMode=false表示禁用交互模式,自动使用提供的参数。执行完该命令后,在当前目录下就会生成一个名为 “my - maven - project” 的 Maven 项目。

4.2 编辑 POM 文件添加依赖

以添加 Spring 框架依赖为例,我们来详细说明在pom.xml文件中<dependencies>标签下添加依赖的具体操作。

首先,打开项目的pom.xml文件,在<dependencies>标签内添加<dependency>标签。然后,我们需要查找 Spring 框架依赖的坐标。可以通过 Maven 仓库网站(如https://mvnrepository.com/ )来搜索所需的依赖。在搜索框中输入 “spring - core”,找到 Spring Core 模块的依赖信息。

假设我们要添加 Spring Core 5.3.9 版本的依赖,在pom.xml中添加如下代码:

 

<dependencies>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-core</artifactId>

<version>5.3.9</version>

</dependency>

</dependencies>

这样就完成了 Spring Core 依赖的添加。如果还需要添加其他 Spring 模块的依赖,比如 Spring Context,同样在<dependencies>标签内继续添加<dependency>标签,并填写相应的坐标信息:

 

<dependencies>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-core</artifactId>

<version>5.3.9</version>

</dependency>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-context</artifactId>

<version>5.3.9</version>

</dependency>

</dependencies>

除了 groupId、artifactId 和 version 这三个必填项外,我们还可以根据项目的需求设置依赖范围(Scope)。例如,如果这个依赖只在测试阶段使用,我们可以添加<scope>test</scope>标签:

 

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring - test</artifactId>

<version>5.3.9</version>

<scope>test</scope>

</dependency>

4.3 构建项目并查看依赖

添加完依赖后,我们使用mvn clean install命令来构建项目。在命令行中进入项目的根目录,执行该命令,Maven 会自动下载并解析声明的依赖。它首先会检查本地仓库中是否已经存在这些依赖,如果不存在,就会从远程仓库(如中央仓库)下载到本地仓库。下载完成后,Maven 会编译项目代码,运行测试用例(如果有),并将项目打包成 JAR 文件,最后将 JAR 文件安装到本地仓库中。

执行mvn clean install命令后,我们可以看到类似如下的输出:

 

[INFO] Scanning for projects...

[INFO]

[INFO] ------------------< com.example:my - maven - project >-------------------

[INFO] Building my - maven - project 1.0 - SNAPSHOT

[INFO] --------------------------------[ jar ]---------------------------------

[INFO]

[INFO] --- maven - clean - plugin:3.1.0:clean (default - clean) @ my - maven - project ---

[INFO] Deleting C:\Users\username\IdeaProjects\my - maven - project\target

[INFO]

[INFO] --- maven - resources - plugin:3.0.2:resources (default - resources) @ my - maven - project ---

[INFO] Using 'UTF-8' encoding to copy filtered resources.

[INFO] Copying 0 resource

[INFO]

[INFO] --- maven - compiler - plugin:3.8.1:compile (default - compile) @ my - maven - project ---

[INFO] Changes detected - recompiling the module!

[INFO] Compiling 1 source file to C:\Users\username\IdeaProjects\my - maven - project\target\classes

[INFO]

[INFO] --- maven - resources - plugin:3.0.2:testResources (default - testResources) @ my - maven - project ---

[INFO] Using 'UTF-8' encoding to copy filtered resources.

[INFO] skip non existing resourceDirectory C:\Users\username\IdeaProjects\my - maven - project\src\test\resources

[INFO]

[INFO] --- maven - compiler - plugin:3.8.1:testCompile (default - testCompile) @ my - maven - project ---

[INFO] No sources to compile

[INFO]

[INFO] --- maven - surefire - plugin:2.22.2:test (default - test) @ my - maven - project ---

[INFO] No tests to run.

[INFO]

[INFO] --- maven - jar - plugin:3.2.0:jar (default - jar) @ my - maven - project ---

[INFO] Building jar: C:\Users\username\IdeaProjects\my - maven - project\target\my - maven - project - 1.0 - SNAPSHOT.jar

[INFO]

[INFO] --- maven - install - plugin:2.5.2:install (default - install) @ my - maven - project ---

[INFO] Installing C:\Users\username\IdeaProjects\my - maven - project\target\my - maven - project - 1.0 - SNAPSHOT.jar to C:\Users\username\.m2\repository\com\example\my - maven - project\1.0 - SNAPSHOT\my - maven - project - 1.0 - SNAPSHOT.jar

[INFO] Installing C:\Users\username\IdeaProjects\my - maven - project\pom.xml to C:\Users\username\.m2\repository\com\example\my - maven - project\1.0 - SNAPSHOT\my - maven - project - 1.0 - SNAPSHOT.pom

[INFO] ------------------------------------------------------------------------

[INFO] BUILD SUCCESS

[INFO] ------------------------------------------------------------------------

[INFO] Total time: 6.819 s

[INFO] Finished at: 2024 - 09 - 10T15:30:00+08:00

[INFO] Final Memory: 32M/309M

[INFO] ------------------------------------------------------------------------

通过mvn dependency:tree命令,我们可以查看项目的依赖树,分析依赖关系。在命令行中执行该命令,输出结果如下:

 

[INFO] Scanning for projects...

[INFO]

[INFO] ------------------< com.example:my - maven - project >-------------------

[INFO] Building my - maven - project 1.0 - SNAPSHOT

[INFO] --------------------------------[ jar ]---------------------------------

[INFO]

[INFO] --- maven - dependency - plugin:3.1.2:tree (default - cli) @ my - maven - project ---

[INFO] com.example:my - maven - project:jar:1.0 - SNAPSHOT

[INFO] +- org.springframework:spring - core:jar:5.3.9:compile

[INFO] | +- org.springframework:spring - jcl:jar:5.3.9:compile

[INFO] | \- org.springframework:spring - core - test:jar:5.3.9:test

[INFO] +- org.springframework:spring - context:jar:5.3.9:compile

[INFO] | +- org.springframework:spring - aop:jar:5.3.9:compile

[INFO] | | \- aopalliance:aopalliance:jar:1.0:compile

[INFO] | +- org.springframework:spring - beans:jar:5.3.9:compile

[INFO] | +- org.springframework:spring - expression:jar:5.3.9:compile

[INFO] | \- org.springframework:spring - core:jar:5.3.9:compile

[INFO] \- org.springframework:spring - test:jar:5.3.9:test

[INFO] +- org.springframework:spring - core:jar:5.3.9:test

[INFO] +- org.springframework:spring - jcl:jar:5.3.9:test

[INFO] +- org.springframework:spring - context:jar:5.3.9:test

[INFO] \- junit:junit:jar:4.13.2:test

[INFO] \- org.hamcrest:hamcrest - core:jar:1.3:test

[INFO] ------------------------------------------------------------------------

[INFO] BUILD SUCCESS

[INFO] ------------------------------------------------------------------------

[INFO] Total time: 1.567 s

[INFO] Finished at: 2024 - 09 - 10T15:35:00+08:00

[INFO] Final Memory: 24M/293M

[INFO] ------------------------------------------------------------------------

从依赖树中,我们可以清晰地看到项目的直接依赖和传递依赖。例如,spring - context依赖除了自身的模块外,还依赖spring - aop、spring - beans、spring - expression和spring - core等模块,而spring - test依赖则进一步依赖了junit和org.hamcrest:hamcrest - core等测试相关的库。通过分析依赖树,我们可以更好地了解项目的依赖结构,方便进行依赖管理和问题排查。

4.4 解决依赖冲突案例分析

在实际项目中,依赖冲突是一个常见的问题。例如,我们的项目中同时引入了A库和B库,A库依赖log4j的 1.2.17 版本,而B库依赖log4j的 2.0 版本,这就导致了log4j版本冲突。

依赖冲突产生的原因主要是不同的依赖对同一个库的版本有不同的要求。当 Maven 在解析依赖时,会根据一定的规则来选择版本,但有时候这些规则并不能满足我们的需求,就会导致冲突的发生。

为了解决这个冲突,我们可以使用 Maven 的依赖管理策略。一种方法是调整依赖声明顺序,Maven 在解析依赖时,会按照pom.xml中依赖声明的顺序来处理。如果我们将需要的log4j版本对应的依赖声明放在前面,Maven 可能会优先选择这个版本。但这种方法并不总是可靠的,因为传递依赖的顺序可能会影响最终的选择。

另一种更可靠的方法是排除冲突依赖。例如,我们希望使用log4j的 2.0 版本,那么可以在A库的依赖声明中排除对log4j 1.2.17 版本的依赖,如下所示:

 

<dependency>

<groupId>com.example</groupId>

<artifactId>A</artifactId>

<version>1.0</version>

<exclusions>

<exclusion>

<groupId>org.apache.logging.log4j</groupId>

<artifactId>log4j</artifactId>

</exclusion>

</exclusions>

</dependency>

然后,再单独声明对log4j 2.0 版本的依赖:

 

<dependency>

<groupId>org.apache.logging.log4j</groupId>

<artifactId>log4j</artifactId>

<version>2.0</version>

</dependency>

这样,Maven 就会忽略A库传递过来的log4j 1.2.17 版本依赖,而使用我们单独声明的 2.0 版本。

通过mvn dependency:tree -Dverbose命令,我们可以查看更详细的依赖信息,包括冲突的依赖项。在命令行中执行该命令,输出结果中会用 “omitted for conflict with” 来标记被排除的冲突依赖,方便我们确认冲突是否已经解决。例如:

 

[INFO] --- maven - dependency - plugin:3.1.2:tree (default - cli) @ my - project ---

[INFO] com.example:my - project:jar:1.0 - SNAPSHOT

[INFO] +- com.example:A:jar:1.0:compile

[INFO] | \- (org.apache.logging.log4j:log4j:jar:1.2.17:compile - omitted for conflict with 2.0)

[INFO] +- com.example:B:jar:1.0:compile

[INFO] | \- org.apache.logging.log4j:log4j:jar:2.0:compile

[INFO] \- org.apache.logging.log4j:log4j:jar:2.0:compile

[INFO] ------------------------------------------------------------------------

[INFO] BUILD SUCCESS

[INFO] ------------------------------------------------------------------------

从输出结果中可以看到,A库传递的log4j 1.2.17 版本依赖被排除了,项目最终使用的是log4j 2.0 版本,成功解决了依赖冲突问题。

五、总结与展望

5.1 总结 Maven 依赖管理基础要点

在本次探索中,我们深入了解了 Maven 依赖管理的核心概念。依赖的基本声明通过pom.xml文件中的<dependency>元素实现,groupId、artifactId和version构成了依赖的唯一标识,让 Maven 能够准确无误地定位和获取所需依赖。

依赖范围(Scope)为我们提供了精细控制依赖在项目不同生命周期阶段的可见性和可用性的能力。compile作为默认作用域,贯穿项目的编译、测试和运行阶段,是项目正常运行的基础保障;provided作用域在编译和测试阶段提供支持,运行时则依赖容器或平台,有效减少部署包大小;runtime作用域在编译时隐身,运行时发挥关键作用;test作用域专注于测试环节,为编写高质量测试用例提供支持;system作用域适用于特殊场景,通过指定本地路径引入依赖;import作用域用于导入 BOM 文件,集中管理依赖版本,避免版本冲突。

版本管理是确保项目依赖稳定性和兼容性的关键。我们可以使用灵活的版本范围表示方法,如[x,y]、[x,y)等,根据项目需求精确控制依赖版本选择。同时,Maven 提供的依赖仲裁机制,如 “就近原则” 和在DependencyManagement中指定版本,有效解决了依赖版本冲突问题。

依赖传递特性虽然方便,但也可能带来冲突。通过合理使用依赖排除和可选依赖,我们可以避免不必要的依赖传递,优化项目的依赖结构。

这些要点相互配合,共同构成了 Maven 依赖管理的强大体系。理解和掌握它们,能够让我们在项目开发中更加高效地管理依赖,避免因依赖问题导致的各种错误和风险,确保项目的顺利进行。

5.2 对进一步学习 Maven 的建议

Maven 作为一款功能强大的项目构建和管理工具,其依赖管理只是冰山一角。对于希望深入掌握 Maven 的开发者来说,还有许多高级特性值得探索。

多模块项目管理是 Maven 的一大优势。在大型项目中,将项目拆分为多个模块,每个模块专注于特定的功能,通过 Maven 的继承和聚合机制进行管理,可以提高项目的可维护性和可扩展性。例如,一个大型的电商项目可能会拆分为商品模块、订单模块、用户模块等,每个模块都有自己独立的pom.xml文件,通过父pom.xml文件进行统一管理和协调。

自定义插件可以让我们根据项目的特定需求,扩展 Maven 的功能。比如,开发一个自动打包并且发布到服务器然后重启服务器的插件,或者定义一款插件自动打包自动运行打包好的构件。通过实现org.apache.maven.plugin.Mojo接口,编写插件的具体逻辑,然后在项目中配置和使用插件,能够极大地提高项目的自动化程度和开发效率。

为了进一步学习这些高级特性,你可以参考 Maven 的官方文档,它提供了详细的使用说明和示例代码,是学习 Maven 的权威资料。此外,一些优秀的技术书籍,如《Maven 实战》等,也对 Maven 的各个方面进行了深入的讲解和实践指导。同时,参与开源项目也是一个很好的学习方式,通过阅读和分析其他开发者在项目中使用 Maven 的经验和技巧,能够拓宽我们的视野,加深对 Maven 的理解和应用能力。

希望大家在 Maven 的学习和实践中不断探索,充分发挥其强大的功能,为项目开发带来更多的便利和价值。


http://www.niftyadmin.cn/n/5865562.html

相关文章

Ubuntu非conda环境python3.8下安装labelme

很久没用过labelme了&#xff0c;造实验数据需要在一个没有conda的Ubuntu20.04安装了python3.8.10的环境下安装labelme&#xff0c;先是直接执行 pip install labelme 执行了多次每次都是卡死&#xff0c;后来先执行pip install pyqt发现也是卡死在同样的地方&#xff0c;发现…

即将发布书籍 - Yocto项目实战教程:高效定制嵌入式Linux系统

以下这本书《Yocto项目实战教程&#xff1a;高效定制嵌入式Linux系统》即将发布&#xff0c;现在请哪位大佬出山写一个序或者推荐&#xff0c;有兴趣的大佬&#xff0c;请联系我&#xff01; Git仓库地址&#xff1a; https://github.com/jerrysundev/Yocto-Project-Book.git …

一篇文章学懂Vuex

一、基于VueCli自定义创建项目 233 344 二、Vuex 初始准备 建项目的时候把vuex勾选上就不用再yarn add vuex3了 store/index.js // 这里面存放的就是vuex相关的核心代码 import Vuex from vuex import Vue from vue// 插件安装 Vue.use(Vuex)// 创建仓库&#xff08;空仓库…

PyVideoTrans:一款功能全面的视频翻译配音工具!

PyVideoTrans是一款功能全面的视频翻译配音工具&#xff0c;专为视频内容创作者设计。它能够将视频中的语言翻译成另一种语言&#xff0c;并自动生成与之匹配的字幕和配音。支持多种语言&#xff0c;包括但不限于中文&#xff08;简繁体&#xff09;、英语、韩语、日语、俄语、…

MySQL数据库连接池泄露导致MySQL Server超时关闭连接

前言 最近做项目&#xff0c;发现老项目出现xxx&#xff0c;这个错误其实很简单&#xff0c;出现在MySQL数据库Server端对长时间没有使用的client连接执行清楚处理&#xff0c;因为是druid数据库&#xff0c;且在github也出现这样的issue&#xff1a;The last packet successf…

拓扑排序的核心算法:BFS应用与实践

目录 一、拓扑排序简介 二、BFS解决拓扑排序的步骤 三、C实现 四、代码解释 五、总结 一、拓扑排序简介 拓扑排序是对有向无环图&#xff08;DAG&#xff09;进行排序的一种方法&#xff0c;使得对于图中的每一条有向边 (u, v)&#xff0c;u 在排序中总是位于 v 的前面。拓…

AIGC-LLAMA模型介绍

LLAMA模型介绍 LLAMA模型介绍LLAMA模型架构模型特点 训练数据代码示例 LLAMA模型介绍 LLAMA&#xff08;LLaMA, Large Language Model Meta AI&#xff09;是Meta&#xff08;前Facebook&#xff09;开发的一系列大型语言模型。LLAMA模型家族旨在提供高效、灵活的语言处理能力…

Java Web框架篇之Spring

Java Web系列文章汇总贴: Java Web知识总结汇总 为什么要有Spring(IoC) Web发展的几个阶段 &#xff08;1&#xff09;初级阶段&#xff1a;使用Model1(JSPJavaBean)/Model2(JspServletJavaBean)/三层模型(表示层(JSP/Servlet)业务逻辑层持久化层)进行开发&#xff1b;&#…