1 依赖管理
1.1 项目对象模型POM
Maven项目下有一个关键配置文件pom.xml
POM( Project Object Model,项目对象模型 ) 是 Maven 工程的基本工作单元,是一个XML文件,包含了项目的基本信息,用于描述项目如何构建,声明项目依赖等等。
所有 POM 文件都需要 project 元素和三个必需字段:groupId,artifactId,version。
能够确定一个点在空间的位置的一个或一组数,叫做这个点的"坐标"。每个构件(artifact)都有自己的唯一"坐标" ,由 groupId,artifactId 和 version 等信息构成。
Maven项目pom.xml文件中,在dependencies标签对中添加依赖坐标。依赖坐标可以通过maven中央库网站https://mvnrepository.com/获取。
比如,项目如果需要添加Junit进行单元测试。
进入后,可以看到Junit有很多个版本。此处选择5.10.1
项目开发需要关注使用的每个框架、库、工具的版本,可以有效避免开发测试过程中出现的一些“莫名其妙”的错误或bug。
这里给大家三个建议:
(1) 建议不使用最新版本,有三个原因:
○ 因为你看到的书或教程往往是基于旧版本
○ 出现问题往往难以搜索到有效的解决方案
○ 依赖该技术的框架或库使用的是旧版本,未能及时更新。
(2) 初学某项新技术,首先参考官方文档。因为官方文档都是匹配版本的。
(3) 关注大的版本号的升级说明。
<!-- junit-jupiter-api -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.10.1</version>
<scope>test</scope>
</dependency>
打开项目pom.xml,将上面这段文件放入dependencies标签对中。
需要特别注意,修改pom.xml后一定要重新载入才能生效。也可以选中项目,右键选中项目右键-Maven-Reload project。
可以看到,项目中引入了4个外部项目jar
为什么我们只添加一个坐标,项目中却引入了4个jar包?
观察maven官网junit-jupiter-api5.10.1构件下方,有3个编译依赖 。
这就是传递依赖,Maven会自动将构件的依赖自动下载到本地仓库,并加入到项目中。再也不用担心丢失依赖jar包导致项目报错了,太强大了!
1.2 查看下载依赖jar
打开本地仓库,可以看到多了很多文件夹,下载的jar都被放入本地仓库。
需要注意的是,groupId通常使用域名地址的反写。比如域名是juipter.junit.org,则groupId是org.junit.juipter。在本地仓库可以按照groupId找到对应的jar
因为域名是世界唯一的。因此groupId使用域名反写,可以有效保证坐标的唯一性。
由于本地仓库已经有了junit-jupiter-api-5.10.1.jar。其他项目如果加入该项目坐标,Maven会首先从本次仓库搜索,不再需要远程下载。
这也是为什么需要将本地仓库配置到Windows系统的非系统盘原因。
1.3 Maven依赖作用范围
Maven中使用 scope 来指定当前包的依赖范围和依赖的传递性。
常见的可选值有:compile, provided, runtime, test, system 等。
scope 主要是用在 pom.xml 文件中的依赖定义部分。
如上节例子junit-jupiter-api-5.10.1就指定依赖范围为test,代码单元测试时该依赖有效。如果没有指定,则默认为compile。可选值含义如下:
compile :为默认的依赖有效范围。如果在定义依赖关系的时候,没有明确指定依赖有效范围的话,则默认采用该依赖有效范围。此种依赖,在编译、运行、测试时均有效。
provided :在编译、测试时有效,但是在运行时无效。例如:servlet-api,运行项目时,容器已经提供,就不需要Maven重复地引入一遍了。
runtime :在运行、测试时有效,但是在编译代码时无效。例如:JDBC驱动实现,项目代码编译只需要JDK提供的JDBC接口,只有在测试或运行项目时才需要实现上述接口的具体JDBC驱动。
test :只在测试时有效,例如:JUnit。
system :在编译、测试时有效,但是在运行时无效。和provided的区别是,使用system范围的依赖时必须通过systemPath元素显式地指定依赖文件的路径。
还有一种非常重要的是import,常用于多模块的dependencyManagement,用于统一管理依赖版本,会在本笔记的第4节介绍。
2 Maven依赖冲突
2.1 什么是依赖冲突
依赖冲突是指项目依赖的某一个jar包,有多个不同的版本,因而造成类包版本冲突。
2.2 依赖冲突产生原因
依赖传递:每个显式声明的类包都会依赖于一些其它的隐式类包,这些隐式的类包会被maven间接引入进来。依赖传递造成项目导入多个不同版本jar冲突,从而造成类包冲突。
maven依赖传递两个原则:最短路径原则、优先导入原则
注意: 并不是所有的依赖冲突会导致项目报错,Maven冲突检查机制可能也做不到上图一个方法这么细。
只是告诉大家,某些构件依赖冲突会导致项目报错。
2.3 查找依赖冲突
运行命令mvn -Dverbose dependency:tree,如果某项依赖提示:
omitted for duplicate表示有jar包被重复依赖。
omitted for conflict with xxx的,说明和别的jar包版本冲突了,而该行的jar包不会被引入。
可以在IDEA中安装插件Maven Helper。它提供一个可视化依赖分析工具。
打开pom.xml,下方可以看到Dependency Analyzer,可以查看依赖树。可以点击Conflicts (冲突),可以查看当前Maven依赖是否存在冲突。如果有,可以选中依赖进行排除。
2.4 排除依赖冲突
可以使用上节介绍的Maven Helper插件可视化查找并排除冲突。也可以通过手动配置排除冲突的依赖,解决冲突。
<dependencies>
<dependency>
<groupId></groupId>
<artifactId></artifactId>
<version></version>
<exclusions>
<exclusion>
<artifactId>XXX</artifactId>
<groupId>XXXX</groupId>
</exclusion>
</exclusions>
</dependency>
3 Maven常用命令
3.1 Maven生命周期
Maven 构建生命周期定义了一个项目构建跟发布的过程。一个典型的 Maven 构建(build)生命周期是由以下几个阶段的序列组成的:
Maven 有以下三个标准的生命周期:
1、Clean 生命周期:
clean:删除目标目录中的编译输出文件。这通常是在构建之前执行的,以确保项目从一个干净的状态开始。
2、Default 生命周期(也称为 Build 生命周期):
validate:验证项目的正确性,例如检查项目的版本是否正确。
compile:编译项目的源代码。
test:运行项目的单元测试。
package:将编译后的代码打包成可分发的格式,例如 JAR 或 WAR。
verify:对项目进行额外的检查以确保质量。
install:将项目的构建结果安装到本地 Maven 仓库中,以供其他项目使用。
deploy:将项目的构建结果复制到远程仓库,以供其他开发人员或团队使用。
3、Site 生命周期:
site:生成项目文档和站点信息。
deploy-site:将生成的站点信息发布到远程服务器,以便共享项目文档。
3.2 常用命令
运行cmd命令行,切换目录到Maven项目根目录下,输入命令,作用如下:
mvn clean 清除编译产生class文件
mvn compile编译项目代码
mvn test 单元测试
mvn package 打包项目
mvn install 将打包的项目安装到本地仓库
可以在IDEA的Maven窗口,更方便执行这些命令。效果和直接在终端输入命令相同。
4 多模块管理
4.1 为什么使用多模块
在Maven项目中,通常会创建多模块项目。对于大型项目,多模块可以帮助有效实现代码管理。
Springboot项目使用多模块,可以非常方便向微服务架构进行项目重构。
此外,我们可以将通常的代码放到一个模块中,把通用代码和应用代码隔离开来,可以实现代码积累,保证通用模块可重用,提高开发效率和代码健壮性。
4.2 ISDP后端多模块划分
项目暂时可以划分为以下三个模块:
mis-core:用于存放通用代码。该模块可以被install到本地仓库,重用于其他项目。
mis-pos:本次开发的Pos应用系统模块。
mis-web:项目启动模块,存放配置文件、项目启动类和SpringBoot项目的controller。
后期如果添加其他功能,如系统管理,可增加新模块mis-system。
模块之间建立如下关系:
mis-pos依赖mis-core,mis-web依赖mis-pos。由于传递依赖,mis-web不需要显性加入依赖坐标,mis-web也会依赖mis-core。
4.3 创建多模块项目
在项目中依次创建三个模块。mis-core,mis-pos,mis-web
项目目录结构参考如。
可以看到pom.xml中多了modules配置。
由于isdp-boot3项目现在是聚合模块,删除根目录下src和targe目录。
可以发现,每个模块下都有pom.xml。
删除根目录下pom.xml中上节加入的junit-jupiter-api-5.10.1依赖。
修改mis-pos模块的pom.xml,加入
<dependencies>
<dependency>
<groupId>edu.scau.mis</groupId>
<artifactId>mis-core</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
修改mis-web模块的pom.xml,加入
<dependencies>
<dependency>
<groupId>edu.scau.mis</groupId>
<artifactId>mis-pos</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
重新加载。
给三个模块新增包,分别为core、pos、web。
删除mis-core和mis-pos的启动类。
mis-web为启动模块。重构启动类名为IsdpApplication
5 小结
本章笔记介绍了Maven的依赖管理、依赖冲突。Maven的生命周期及常用命令。创建了isdp-boot3项目的多模块。
下一篇笔记将引入SpringBoot3依赖,创建SpringBoot3项目。