三、maven进阶
3.1pom.xml文件
maven的核心配置文件 pom.xml
,定义了项目的基本信息、依赖、构建配置等。
Maven Repository: Search/Browse/Explore maven中央仓库链接
3.2坐标
3.2.1坐标的概念
在 Maven 中坐标是构件的唯一标识,Maven 坐标的元素包括 groupId 、artifactId 、version 、packaging、classifier。上述5个元素中,groupId、artifactId、version 是必须定义的,packaging 是可选的 ( 默认为 jar )还有var或pom。
3.2.2坐标的意义
- groupId:组织标识,一般为:公司网址的反写+项目名(唯一标识)
- artifactId:项目名称,一般为:项目名-模块名
- version:版本号 形式为0.0.1-SNAPSHOT:
- 第一个 0 表示大版本号,第二个 0 表示分支版本号,第三个 0 表示小版本号
- SNAPSHOT -- 快照版本,ALPHA -- 内侧版本,BETA -- 公测版本,RELEASE -- 稳定版本,GA -- 正式发布
- packaging:打包的方式,如:pom, jar, maven-plugin, ejb, war, ...
- clissifier:用来帮助定义构件输出的一些附属构件。
自己项目的坐标如下:
第三方项目坐标如下:

3.3依赖
3.3.1依赖的意义
在 Maven 中,依赖(Dependency) 是指你的项目需要使用的 外部库(比如别人写好的工具包、框架等)。Maven 通过依赖管理,帮你自动下载这些库,并确保版本兼容,避免手动操作的麻烦。
想象你在做一道菜:
-
你的代码 = 你的菜(比如"红烧肉")。
-
依赖 = 需要的调料(比如酱油、糖、八角)。
如果没有酱油,菜就做不出来,但你不必自己酿酱油,直接买现成的就行。
Maven 的依赖就是帮你自动"买调料"(下载库),并确保"调料"的版本是对的(比如"生抽"而不是"老抽")。
3.3.2依赖的核心作用
-
省去手动下载
-
传统方式:上网找 JAR 包 → 下载 → 放到项目里 → 可能版本冲突。
-
Maven 方式:在
pom.xml
中写一行配置,自动下载并管理。
-
-
解决依赖冲突
- 比如你的项目用了库 A,而库 A 又需要库 B,Maven 会自动把 A 和 B 都下载好(传递性依赖)。
-
版本统一管理
- 避免团队中每个人用的库版本不同导致问题。
3.3.3依赖的使用
例如我们的项目需要进行单元测试,则需要使用到junit-4.9.jar包,使用maven引用该依赖的方式如下:
java
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.9</version>
<!--依赖范围-->
<scope>test</scope>
</dependency>
<dependency>
<groupId>cn.tx.maven</groupId>
<artifactId>Hello</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
属性说明:
**三维坐标:**引用依赖包的三维坐标,用来定位该依赖包;
**scope:**控制该依赖包在什么情况下会被加到 classpath 中;
3.3.4第三方依赖的查找方法
我们在不确定所需引用的第三方依赖包的坐标时,通过maven的中央仓库进行查找,网址: https://mvnrepository.com/;
3.4依赖范围
Maven项目在开发工程中有三套classpath
- 主代码:main下面的都是主代码在编译的时候的依赖
- 测试代码:test下是测试代码编译的时候的依赖
- 运行时:main代码在运行的时候对包的依赖
依赖范围的使用,通过在引用第三方依赖时的<scope></scope>标签进行设置,例如:

java
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.9</version>
<!--依赖范围-->
<scope>test</scope>
</dependency>
共 6 种 scope,包括:compile 、provided 、runtime 、test 、system、import。例如上图的junit,只在测试中使用,则选择test即可,默认为compile
- **Compile:**编译依赖范围。默认使用此依赖范围,其下的maven依赖,对于编译,测试,运行classpath都有效。(默认)
- **Test:**测试依赖范围。只对测试classpath有效,编译主代码或运行项目时无法使用此依赖。典型例子如junit。
- **Provided:**已提供依赖范围。其对于编译与测试classpath有效,运行时无效。如在web开发时,只有在编译和测试时才用到servlet-api,将其设置为此范围,在运行时servlet-api由web容器提供,无须依赖。并且在打war包时,此范围的依赖不会打在WEB-INF/lib下。(tomcat自带api,如果provided有会发生冲突,或者覆盖)
- **Runtime:**运行时依赖范围。与provided相对,运行时classpath有效。典型例子如jdbc(编写是接口规范运行是提供具体实现类需要jar包)。
3.5依赖传递和可选依赖
3.5.1依赖传递
应用场景:
第一直接依赖: HelloFriend项目依赖Hello项目
第二直接依赖: MakeFriend项目依赖HelloFriend项目

makeFriend项目只依赖了HelloFriend,但是也把Hello依赖进来了。
传递依赖是会受到依赖范围的影响的,具体来看结果如下:

3.5.2依赖阻断
例如我们在HelloFriend项目里面的Hello依赖处添加该配置
<optional>true:表示Hello只在HelloFriend中


则makeFriend项目里面就不会再引入Hello的依赖。
3.5.3可选依赖
如果我们需要在依赖中明确的排除掉某一依赖,则可以使用exclusion属性,排除掉引用的依赖,如图:

3.6仓库
3.6.1 仓库的概念
Maven 仓库(Repository)是存放和管理项目依赖(第三方库、插件等)的地方,就像是一个**"仓库管理员"**,帮你自动下载、缓存和查找需要的文件。
仓库的类型有:
- 本地(local)
- 中央(central)
- 远程(remote)
3.6.2本地仓库(Local Repository)
-
作用:相当于你的"个人书架",存储你所有项目下载过的依赖。
-
位置 :默认在用户目录下的
.m2/repository
(例如:C:\Users\你的用户名\.m2\repository
)。如果要修改默认位置,在 %Maven_HOME%\conf 目录中的 Maven 的 settings.xml 文件中定义另一个路径。 -
特点:
-
第一次下载的依赖会缓存到这里,下次直接用,无需重复下载。
-
只有你自己的电脑能访问。
-
3.6.3中央仓库(Central Repository)
-
作用 :Maven 官方维护的公共图书馆,存储了绝大多数开源库(如 Junit、Spring 等)。
-
特点:
-
无需配置,Maven 默认从这里下载依赖。
-
如果中央仓库没有你需要的依赖,需要手动添加其他远程仓库。
-
3.6.4远程仓库(Remote Repository)
-
作用:除了中央仓库以外的其他仓库,可能是公司内部的私有仓库或第三方公共仓库。
-
常见例子:
-
公司私有仓库(如 Nexus、Artifactory):存放公司内部开发的私有库。
-
第三方公共仓库(如阿里云镜像仓库):加速下载(替换默认的中央仓库)。
-
-
配置方式 :在
pom.xml
或settings.xml
中声明:
java
<repositories>
<repository>
<id>aliyun</id>
<url>https://maven.aliyun.com/repository/public</url>
</repository>
</repositories>
3.6.5三者协作流程
-
当你运行
mvn install
:-
Maven 先检查本地仓库,如果有依赖,直接使用。
-
如果本地没有,从中央仓库或配置的远程仓库下载,并缓存到本地仓库。
-
如果是公司私有库,会从私有远程仓库下载。
-
-
优先顺序 :
本地仓库 → 远程仓库(按配置顺序) → 中央仓库
仓库类型 | 比喻 | 特点 |
---|---|---|
本地仓库 | 你家书架 | 快速拿书,但书不全时要去图书馆借。 |
远程仓库 | 公司/学校的图书馆 | 书更全,但需要联网访问。 |
中央仓库 | 国家图书馆 | 书最多,但距离远(下载可能慢)。 |
3.7生命周期
Maven的生命周期是对所有的构建过程进行抽象和统一。Maven的生命周期是抽象的,这意味着生命周期本身不做任何实际的工作,生命周期只是定义了一系列的阶段,并确定这些阶段的执行顺序。而在执行这些阶段时,实际的工作还是由插件来完成的。这种思想与设计模式中的模板方法非常相似。
Maven 有 3 个独立的生命周期,每个生命周期包含不同阶段:
(1) clean
生命周期
目的 :清理项目。
主要阶段:
pre-clean
→clean
(删除target
目录) →post-clean
(2) default
生命周期(最常用)
目的 :构建和部署项目。
关键阶段(按顺序执行):
-
validate
(验证项目正确性) -
compile
(编译源代码) -
test
(运行单元测试) -
package
(打包,如生成JAR/WAR
文件) -
verify
(检查测试结果) -
install
(将包安装到本地仓库) -
deploy
(部署到远程仓库)
(3) site
生命周期
目的 :生成项目文档和报告。
主要阶段:
pre-site
→site
(生成文档) →post-site
→site-deploy
(发布文档)
把 Maven 生命周期比作 "盖房子":
-
clean
:拆掉旧房子(清理target
)。 -
default
:-
compile
= 打地基(编译代码)。 -
test
= 检查工程质量(运行测试)。 -
package
= 封顶完工(打包)。 -
install
= 把房子登记到本地房产局(本地仓库)。
-
-
site
:生成房屋使用说明书(项目文档)。
3.8maven的继承和聚合
3.8.1继承的意义
继承允许子模块从父模块继承配置信息,类似于 Java 中的类继承机制。作用是为了
-
统一管理公共依赖
-
统一配置插件
-
统一管理属性
-
减少重复配置
3.8.2可继承的元素
groupId :项目组 ID ,项目坐标的核心元素;
version :项目版本,项目坐标的核心元素;
description :项目的描述信息;
organization :项目的组织信息;
inceptionYear :项目的创始年份;
url :项目的 url 地址
develoers :项目的开发者信息;
contributors :项目的贡献者信息;
distributionManagerment :项目的部署信息;
issueManagement :缺陷跟踪系统信息;
ciManagement :项目的持续继承信息;
scm :项目的版本控制信息;
mailingListserv :项目的邮件列表信息;
properties :自定义的 Maven 属性;(统一管理版本)
dependencies :项目的依赖配置;
dependencyManagement :醒目的依赖管理配置;
repositories :项目的仓库配置;
build :包括项目的源码目录配置、输出目录配置、插件配置、插件管理配置等;
reporting :包括项目的报告输出目录配置、报告插件配置等。
3.8.3IDEA实现maven的继承
创建父类项目


创建子类项目core



以同样的方式创建manage和portal项目:

至此,一个由parent统一管理core,manage和portal的mavan项目就创建好了;
观察父子项目的pom文件配置


3.8.4继承的依赖管理
父类直接引用依赖,如果在父类的dependencies内直接引用依赖,则子类都会继承该依赖,以mybatis为例:

父类通过dependencyManagement管理依赖,子类不会默认继承该依赖,但是当子类使用该依赖时无需考虑版本信息,直接继承父类dependencyManagement中设置的版本号(Version),以log4j为例:


3.8.5聚合管理
我们在平时的开发中,项目往往会被划分为好几个模块,比如common公共模块、system系统模块、log日志模块、reports统计模块、monitor监控模块等等。这时我们肯定会出现这么一个需要,我们需要一次构件多个模块,而不用每个模块都去mvn;
以上面得父子项目为例,当我们对parent进行mvn install时,会对core,manage和portal项目均进行install操作:


3.8.6properties属性的使用
通过 properties元素用户可以定义一个或多个 maven 属性,然后在 maven 的其他地方使用 ${属性名称} 的方式引用该属性,这种做法的意义在于消除重复和统一管理。比如,需要在多个地方重复声明同样的 SpringFramework 版本,现在只需要在一个地方声明就可以。