Maven 坐标
Maven 的很强大的一个功能就是管理项目依赖,为了能自动化的精确获取到项目依赖,Maven 就必须为其唯一标识,Maven 通过坐标来构建唯一标识。
比如上一章中的一个 Maven 的 java 工程,我们在创建工程时已经书写了具体的坐标,我们可将该工程 install 到本地仓库,我们在分模块开发时如果依赖该工程,直接编写该工程的 jar 包的坐标即可!
平面几何中,使用 (x,y) 坐标来表示平面中的任何一个点。Maven 中拥有数量巨大的构件,就是 jar、war 等文件,Maven 自己创建了一种坐标规则,只要我们指定正确的坐标,Maven 就会到中央仓库中下载这些构建,Maven 的中央仓库中包含了世界上流行的大部分构件。
我们来看一组坐标
<!-- 组织名称。项目属于哪个组。例如Spring-core,Spring-context都是属于SpringFramework组的。-->
<groupId>com.cad.maven</groupId>
<!--项目名称。 -->
<artifactId>HelloWorld</artifactId>
<!-- 定义当前项目的版本-->
<version>0.0.1</version>
<!-- 定义项目的打包方式。例如jar、war。不指定默认为jar -->
<packaging>jar</packaging>
Maven 的依赖管理
什么叫依赖管理
再此之前,你要知道什么是依赖管理!就是对项目所有依赖的 jar 包进行规范化管理。
maven 项目管理所依赖的 jar 包不需要手动向工程添加 jar 包,只需要在 maven 的核心配置文件 pom.xml 添加 jar 包的坐标,就会自动从 maven 仓库中下载相对于的 jar 包,如一个ssh工程,它需要 Struts2、Hibernate、spring 等 jar 包。
添加依赖的一种实用方法
添加依赖的方法有几种,在这就不一一展开说了,教大家一种直观并且个人觉得很实用的方法,比如,你需要某个 Struts2-core 这个 jar 包,你可以到 https://mvnrepository.com/ 里面搜索,搜索出来有各中版本的用你选择。
你需要哪个版本的就点进去 copy 哪个版本的依赖代码粘贴在 pom.xml 中即可!
依赖范围
依赖范围就是用来控制依赖应该在何时存在,例如 junit 包只需要在测试时存在,项目正式运行时就不需要了。
Maven 有以下几种依赖范围
-
compile:没有指定,默认使用该依赖范围。使用此依赖范围,对于主代码、测试、运行时都会被引入各自的 classpath。例子是 spring-core,在主代码、测试、运行时都需要这个依赖。
-
test:测试依赖范围。使用此依赖范围的Maven依赖,只会被测试 classpath 引入。例子是 JUnit,只有在测试时需要。
-
provided:使用此依赖范围的 Maven 依赖,会被主代码、测试等 classpath 引入,在运行时无效。例子是 servlet-api,编译主代码和测试时需要,但在运行时由于容器会提供,所以可能会出现冲突,就不需要 Maven 再引入依赖。
-
runtime:运行时依赖范围。使用此依赖范围的 Maven 依赖,只有项目运行时会引入依赖。例子是 JDBC 驱动,在编译主代码时无效,只有测试运行还有运行时需要引入。
依赖传递
什么叫依赖传递呢?
我们说一个简单的例子,例如我们的 B 项目依赖 C 项目,我们的 A项目依赖于 B项目,C 项目的很多依赖在 A 项目中也需要,Maven 有依赖传递机制,我们 A 项目既然依赖了 B 项目,就不需要考虑 B 项目依赖了什么,也不用担心使用不了 C 项目的依赖,再重复定义依赖,Maven 会解析各个直接依赖的pom文件,将那些间接依赖引入到当前项目中。
依赖传递范围
我们知道每个依赖都有它的传递范围,第一直接依赖的范围和第二直接依赖的范围决定了依赖传递范围。我们用下图来说明一下。
我们再来举个例子来理解该表,例如我们的A项目依赖 Spring-core.jar,这是第一直接依赖,其依赖范围是 test。而 Spring-core.jar又依赖于commons-logging.jar,这是第二直接依赖,也就对应上图的传递依赖,其依赖范围是 compile。因此,对照表,即可得知,A 项目是 commons-logging.jar 的一个范围是 test 的传递性依赖,也就是说在测试的时候才会将 commons-logging.jar 引入。
依赖冲突
引入这两个依赖
<dependencies>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-spring-plugin</artifactId>
<version>2.3.24</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
</dependencies>
发现这两个 jar 包都同时依赖了 spring-beans
但是是 spring-beans-3.0.5 加入到了工程中,而我们希望的是 spring-beans-4.2.4 加入到工程中,这就造成旅客依赖冲入,那应该怎么解决呢?
解决依赖冲突
1. 第一声明这优先原则
在 pom.xml 文件定义依赖,先声明的依赖为准。
例如:我们将这两个依赖顺序颠倒,系统将导入 spring-beans-4.2.4
2. 路径近者优先原则
比如,A 依赖 spring-beans-4.2.4,A 依赖 B 依赖 spring-beans-3.0.5,则 spring-beans-4.2.4 优先被依赖在 A 中,因为 spring-beans-4.2.4 相对 spring-beans-3.0.5 被 A 依赖的路径最近
所以根据路径优先原则,只需要在 pom.xml 中加入 spring.beans-4.2.4 的依赖即可!
3. 排除依赖
例如在 struts2-spring-plugin 的设置中添加排除依赖
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-spring-plugin</artifactId>
<version>2.3.24</version>
<!-- 排除 spring-beans 的依赖 -->
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</exclusion>
</exclusions>
</dependency>
4. 锁定版本
面对众多的依赖,有一种方法不用考虑依赖路径、声明优先等因素,可以采用直接锁定版本的方法确定依赖构建的版本,此方法在企业开发中常用。
<!-- 锁定版本 4.2.4-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
</dependencies>
</dependencyManagement>
ps:在工程中锁定依赖的版本并不代表在工程中添加了依赖,如果工程中需要添加锁定版本的依赖,则需要单独添加 <dependencies></dependencies>
标签,并且可以不用指定版本了!
maven 的仓库
Maven可以在某个统一的位置存储所有项目的依赖,这个位置就是仓库。Maven 项目中只需要声明依赖的坐标,Maven 会根据坐标自动寻找仓库中的依赖,并使用他们。而我们的项目也可以安装部署到仓库中,使其他项目使用。
根据 Maven 坐标定义每个构建在仓库中唯一存储路径大致为:groupId/artifactId/version/artifactId-version.packaging。
仓库的分类
Maven仓库分为本地仓库和远程仓库。Maven 根据坐标寻找依赖时,会先到本地仓库查找,如果有则直接使用,如果没有则到远程仓库查找,如果查找到则下载到本地仓库使用,没有查找到就报错。
远程仓库又分为中央仓库和私服还有其他公开的远程仓库。私服是一种特殊的远程仓库,我们可以在公司内部部署一个私服,这样每个员工使用依赖时就不用每个人都去中央仓库下载,而是去局域网的私服下载,还可以把公司内部的项目放在私服上,供所有人使用,节省了带宽和时间。
本地仓库
默认情况下,本地仓库的地址是用户目录下的 .m2/repository/ ,但是我们可以编辑 settings.xml 文件来自己设置目录,前面我们有讲过,就不再多说。
中央仓库
默认的中央仓库地址是 https://mvnrepository.com/。 中央仓库包含了世界上大部分开源依赖。
私服
私服架设在局域网内,供局域网内的用户使用。Maven 需要下载依赖时,先请求私服,如果私服没有,则从外部的远程仓库下载,自己还可以向私服上上传自己的项目,供局域网使用。
私服有很多优点。
- 节省自己带宽:大量对于外部仓库的访问会占用很多带宽。
- 没网的时候也可以使用
- 可以部署自己的项目
ps: 关于搭建私服环境、将项目发布到私服和从私服下载 jar 包,网上有很多资料,感兴趣自行百度!
maven 的插件
我们前面说 Maven 的核心仅仅定义了抽象的生命周期,具体的任务是由插件完成的。为了让用户不用自己配置插件就能构建Maven项目,Maven 在核心为一些主要的生命周期绑定了很多插件,当用户执行生命周期阶段时,对应的插件就会起作用。
自定义绑定插件
<build>
<plugins>
<!--指定编译插件用的jdk版本-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>utf-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
ps:部分内容整理于网络,如有侵权,请私聊!