1. 依赖配置
- groupId,必选,实际隶属项目 (基本坐标)
- artifactId,必选,其中的模块 (基本坐标)
- version 必选,版本号 (基本坐标)
- type 可选,依赖类型,默认 jar
- scope 可选,依赖范围,默认 compile
- optional 可选,标记依赖是否可选,默认 false
- exclusion 可选,排除传递依赖性,默认空
大部分依赖声明只包含基本坐标。
2. 依赖范围
maven 项目有三种 classpath(编译,测试,运行),scope 用来表示与 classpath 的关系,总共有 五 种
- compile:编译,测试,运行
- test:测试
- provided:编译,测试
- runtime:运行
- system:编译,测试,同 provided,但必须指定 systemPath,慎用
依赖范围有效运行期:
Maven 依赖 jar 包冲突解决
1. 判断 jar 是否正确的被引用
在项目启动时加上 VM 参数:
-verbose:class
项目启动的时候会把所有加载的 jar 都打印出来 类似如下的信息:classpath 加载的 jar .... 具体 load 的类 ...
我们可以通过上面的信息查找对应的 jar 是否正确的被依赖,具体类加载情况,同时可以看到版本号,确定是否由于依赖冲突造成的 jar 引用不正确;
通过 maven 自带的工具:
mvn dependency:tree
具体后面可以加 -Dverbose 参数 ,详细参数可以去自己搜,这里不详细介绍。
比如分析如下 POM
运行:
mvn dependency:tree -Dverbose
2. 冲突的解决
1)在 pom.xml
中引用的包中加入 exclusion
,排除依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.5.3</version>
<exclusions>
<exclusion>
<artifactId>spring</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
</exclusions>
</dependency>
去除全部依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.5.3</version>
<exclusions>
<exclusion>
<artifactId>*</artifactId>
<groupId>*</groupId>
</exclusion>
</exclusions>
</dependency>
2)在 ide 中右击进行处理,处理完后在 pom.xml 中也会添加 exclusion 元素
3. 传递性依赖
Maven 传递依赖的关系
4. 可选依赖
有时候我们不想让依赖传递,那么可配置该依赖为可选依赖,将元素 optional 设置为 true 即可,例如:
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
<optional>true</optional>
</dependency>
那么依赖该项目的另一项目将不会得到此依赖的传递。
5. 排除依赖
当我们引入第三方 jar 包的时候,难免会引入传递性依赖,有些时候这是好事,然而有些时候我们不需要其中的一些传递性依赖。如当我们引入 spring 包时,我们不想引入传递性依赖 commons-logging
,我们可以使用 exclusions
元素声明排除依赖,exclusions
可以包含一个或者多个exclusion
子元素,因此可以排除一个或者多个传递性依赖。
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.8.RELEASE</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
6. 依赖归类
如果我们项目中用到很多关于 Spring Framework 的依赖,它们分别是org.springframework:spring-core:2.5.6
, org.springframework:spring-beans:2.5.6
,org.springframework:spring-context:2.5.6
,它们都是来自同一项目的不同模块。因此,所有这些依赖的版本都是相同的,而且可以预见,如果将来需要升级 Spring Framework,这些依赖的版本会一起升级。因此,我们应该在一个唯一的地方定义版本,并且在 dependency 声明引用这一版本,这一在 Spring Framework 升级的时候只需要修改一处即可。
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<springframework.version>4.3.8.RELEASE</springframework.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${springframework.version}</version>
</dependency>
</dependencies>
7. 管理依赖
mvn dependency:list 表示依赖列表
mvn dependency:tree 表示依赖列表
mvn dependency:analyze 查找出在编译和测试中未使用但显示声明的依赖 Unused declared dependencies found:
8. 仓库
何为 Maven 仓库
在 Maven 世界中,任何一个依赖、插件或者项目构建的输出,都可以称为构件,任何一个构件都有一组坐标唯一标识。
以前传统的开放模式中,每个项目都有 lib 目录,各个项目 lib 目录下的内容存在大量的重复,这样不仅造成磁盘空间的浪费,而且也难 于管理。
Maven 在某个统一的位置存储所有项目的共享的构件,这个统一的位置,我们就称之为仓库。(仓库就是存放依赖和插件的地方)
仓库的布局
任何一个构件都有其唯一的坐标,根据这个坐标可以定义其在仓库中的唯一存储路径,这便是 Maven 的仓库布局方式。 该路径与坐标的大致对应关系为:
groupId/artifactId/version/artifactId-version.packaging
仓库的分类
对于 Maven 来说,仓库只分为两类:本地仓库和远程仓库。
当 Maven 根据坐标寻找构件的时候,它首先会查看本地仓库,如果本地仓库存在此构件,则直接使用;如果本地仓库不存在此构件,Maven 就会去远程仓库查找,发现需要的构件,下载到本地仓库再使用。如果本地仓库和远程仓库都没有,Maven 就会报错。
私服是一种特殊的远程仓库,为了节省带宽和时间,应该在局域网内架设一个私有的仓库服务器,用其代理所有外部的远程仓库。内部的项目还能部署到私服上供其他项目使用。
本地仓库
一般来说,在 Maven 项目目录下,没有诸如 lib/ 这样用来存放依赖文件的目录。当 Maven 在执行编译或者测试时,如果需要使用依赖文件,它总是基于坐标使用本地仓库的依赖文件。
默认情况下,本地仓库地址为 C:\Users\用户名\.m2\repository\
,有时候,因为某些原因(C 盘空间不够,系统盘),需要自定义本地仓库的目录地址,这时,可以编辑 Maven 目录下 settings.xml,设置 localRepository 元素的值为想要的仓库地址。例如:
一个构件只有在本地仓库中之后,才能由其他 Maven 项目使用。首先必须得以构件并安装到本地仓库中。在项目中执行 mvn clean install
命令,Install 插件的 install 目标将项目的构件输出文件安装到本地仓库。
远程仓库
当用户执行 maven 命令之后,Maven 会根据配置和需要从远程仓库下载构件到本地仓库。
这好比藏书,例如我要读<红楼梦>,会先检查自己的书房是否藏了这本书,如果发现没有这本书,于是就跑去书店买一本回来,放在书房里。红楼梦>
本地仓库就好比书房,我需要读书的时候先从书房找,相应的,Maven 需要构件的时候,先从本地仓库找。当无法从本地仓库找到需要的构件的时候,就会从远程仓库下载构件到本地仓库。
私服
私服是一种特殊的远程仓库,它是架设在局域网内的仓库服务,私服代理广域网上的远程仓库,供局域网内的用户使用。当 Maven 需要下载构件的时候,它从私服请求,如果私服上不存在该构件,则从外部远程仓库下载,缓存在私服上之后,再为 Maven 的下载请求提供服务。
私服的好处:
- 节省自己的外网带宽
- 加速 Maven 构建
- 部署自己内部的第三方构件
- 提高稳定性,增强控制
- 降低中央仓库的负荷。
镜像
- 如果仓库
X
可以提供仓库Y
存储的所有内容,那么就可以认为X
是Y
的一个镜像。如果配置X
的镜像,那么对于仓库Y
的任何请求都会转至X
仓库。 镜像常见的用法是结合私服,由于私服可以代理任何外部的公共仓库,因此,对于组织内部的 Maven 用户来说,使用一个私服地址就等于使用了所有需要的外部仓库。任何需要的构件都可以从私服获得,私服就是所有仓库的镜像。这时可以配置这样的一个镜像,见下图。
该例中
<mirrorOf>
的值为星号,表示该配置是所有 Maven 仓库的镜像,任何对于远程仓库的请求都会转至http://172.168.10.100:8081/nexus/content/groups/public/
如果镜像仓库需要认证,则配置一个ID
为nexus
的<server>
即可。- 需要注意:由于镜像仓库完全屏蔽了被镜像的仓库,当镜像仓库不稳定或者停止服务的时候,Maven 将无法访问镜像仓库,因此将无法下载构件。
9. 生命周期
何为生命周期
Maven 的生命周期就是为了对所有的构建过程进行抽象和统一,这个生命周期包含了项目的清理、初始化、编译、测试、打包、集成测试、验证、部署和站点生成等几乎所有的构建步骤。
Maven 的三大生命周期
Maven 有三套相互独立的生命周期,请注意这里说的是”三套”,而且”相互独立”,这三套生命周期分别是:
- Clean Lifecycle 在进行真正的构建之前进行一些清理工作。
- Default Lifecycle 构建的核心部分,编译,测试,打包,部署等等。
- Site Lifecycle 生成项目报告,站点,发布站点。
每个生命周期包含一些阶段(phase),这些阶段是有顺序的,并且后面的阶段依赖于前面的阶段。以 clean
生命周期为例,它包含的阶段有 pre-clean
,clean
和post-clean
。当用户调用pre-clean
的时候,只有pre-clean
阶段得以执行。当用户调用clean
时候,pre-clean
和clean
阶段会得以顺序执行。
clean 生命周期
Clean 生命周期的目的是清理项目,它包含三个阶段:
- pre-clean 执行一些清理前需要准备完成的工作
- clean 清理上一次构建生成的文件
- post-clean 执行一些清理后需要完成的工作。
default 生命周期
Default 生命周期定义了真正构建时所需要执行的所有步骤,它是所有生命周期中最核心的部分,这里,只解释一些比较重要和常用的阶段:
Validate 验证项目是否正确且所有必要的信息都可用。 generate-sources 为包含在编译范围内的代码生成源代码 process-sources 处理源代码,如过滤值。 generate-resources 生成所有需要在打包过程中的资源文件。 process-resources 复制并处理资源文件,至目标目录,准备打包。 compile编译项目的源代码。 process-classes 为编译生成的文件做后期工作。 generate-test-sources 为编译内容生成测试源代码 process-test-sources 处理测试源代码。 generate-test-resources 生成测试需要的资源文件。 process-test-resources复制并处理资源文件,至目标测试目录。 test-compile 编译测试源代码。 process-test-classes 对测试编译生成的文件做后期处理。 test使用合适的单元测试框架运行测试。这些测试代码不会被打包或部署。 prepare-package 在真正打包之前,执行一些打包的必要操作。 package 接受编译好的代码,打包成可发布的格式,如 JAR 。 pre-integration-test 执行一些在集成测试运行之前需要的动作。 integration-test 如果有必要,处理包并发布至集成测试环境。 post-integration-test 执行一些在集成测试运行之后需要的动作。 Verify 执行所有的检查,验证包是否有效,质量是否合格。 install 将包安装至本地仓库,以让其它项目依赖。 deploy将最终的包复制到远程的仓库,以让其它开发人员与项目共享。
site 生命周期
Site 生命周期的目的是建立和发布项目站点,Maven 能够基于 POM 所包含的信息,自动生成一个友好的站点,方便团队交流和发布项目信息。该生命周期包含如下阶段:
- Pre-site 执行一些在生成项目站点发布到服务器上。
- Site 生成项目站点文档。
- Post-site 执行一些在生成项目站点之后需要完成的工作。
- Site-deploy 将生命的项目
文档信息
- 本文作者:Zhang jinmiao
- 本文链接:http://zhangjinmiao.github.io/maven/2019/03/31/Maven-%E4%BB%8B%E7%BB%8D.html
- 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)