本文已参与「新人创作礼」活动,一起开启掘金创作之路。
Maven 依赖
Maven 中最关键的部分, 使用 Maven 最主要就是使用它的依赖管理功能.
添加依赖
当 A.jar 包中使用到了 B.jar 包中的某些类时, A 就对 B 产生了依赖. 那么如何在项目中以依赖的方式引入我们需要的 jar 包呢 ?
在 pom.xml 文件中, 使用 <dependency> 标签 指定被依赖的 jar 包的在本地仓库/远程仓库中的 gav 坐标就可以了.
<!--添加依赖-->
<dependencies>
<!--添加 junit 的 jar 包的依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.9</version>
<scope>test</scope>
</dependency>
<!--添加 Hello 的 jar 包的依赖-->
<dependency>
<groupId>me.gacl.maven</groupId>
<artifactId>Hello</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
dependency 标签的子标签的含义 :
- groupld 依赖的坐标
- artifactld 依赖的坐标
- version 依赖的坐标
- optional 标记依赖是否可迭
- scope 依赖范围, 默认为 compile
- exclusions 用来排除传递性依赖
依赖的范围
依赖范围 scope 用来控制依赖和 编译, 测试, 运行的 classpath 的关系.
<scope> 标签可以设置依赖的范围. 可选值 : compile , test , provided , runtime 四个.
- compile: 默认的编译依赖范围.
对于编译, 测试, 运行三种 classpath 都有效. 参与打包, 参与部署. - provided:对运行无效的依赖范围.
对于编译, 测试的 classpath 都有效, 但对于运行无效. 不参与打包和部署. - test:测试依赖范围.
只对于测试 classpath 有效. 不参与打包和部署. - runtime : 运行时提供.
在运行的时候才会依赖, 在编译的时候不会依赖.
从项目结构的角度理解 compile 和 test 的不同.
对于该项目来说, 主程序是需要 Hello.jar 包中的类的, 测试程序由于要调用主程序, 所以也需要 Hello.jar 包中的类. 所以 Hello.jar 是 compile 范围的依赖, compile 范围的依赖对于主程序和测试程序都应该有效. 而对于 Junit.jar 中的类, 只有在测试程序中才会使用到, 主程序是不需要的. 所以 Junit.jar 是 test 范围的依赖, test 范围的依赖只对于测试有效.
依赖的传递性
如果项目 A 依赖于项目 B, 项目 B 依赖于项目 C, 那么项目 A 它也是依赖于项目 C 的. 这就是依赖的传递性.
当然了, 这种依赖只对compile范围的依赖有效. 也就是说, 如果 B 依赖 C 的范围不是 compile, 那么 A 就不能依赖 C.
依赖传递性的架包冲突问题
两条准则: 路径最短者优先, 路径相同, 先声明者优先.
依赖的排除
排除依赖:就是将该模块中的 某个 jar 包给移除掉. 或者将一个依赖中的子依赖排除掉.
依赖传递性冲突问题解决 :
- 通过
调整 dependency 的顺序来解决:哪个依赖的顺序在前面就依赖哪个. 自己添加一个 dependeny来解决:因为该路径是最小的.通过 exclusions 元素排除不想要的传递性依赖.
统一管理所依赖的 jar 包的版本
对同一个框架的一组 jar 包最好使用相同的版本. 可以将 jar 包的版本信息提取出来, 统一进行管理.
① 统一定义版本号. 标签 spring.version 是自定义标签, 可以写其他的.
<!-- 统一定义版本号 -->
<properties>
<spring.version>4.3.7.RELEASE</spring.version>
<mybatis.version>3.4.2</mybatis.version>
</properties>
② 引用前面声明的 版本号
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>
Maven 继承
Maven 继承是多模块工程的基础. 继承可以使子 pom 获得父 pom 中的各项元素和依赖的配置, 在简化 pom 的同时, 还能够促进各个模块配置的一致性. 实现对子 pom 进行统一配置和依赖管理. 可以有效的避免多个子模块使用依赖版本不一致的情况, 有助于降低依赖冲突的几率.
依赖的继承
在 父 pom 中 <dependencyManagement> 标签中配置的依赖既不会给 parent 引入依赖, 也不会给它的子模块引入依赖, 仅仅表示它的配置是可继承的.
① 父模块中定义依赖
<!-- 统一定义版本号 -->
<properties>
<spring.version>4.3.7.RELEASE</spring.version>
</properties>
<!-- 父模块统一管理依赖 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
② 子模块中使用依赖
需要声明 groupId 和 artifactId, 表示当前配置是继承于父 POM 的, 从而直接使用父 POM 的版本对应的资源. 不需要定义版本号. 使用父 pom 中定义的版本. 只有子模块配置了继承的元素, 才会真正的有效, 否则 maven 是不会加载父模块中声明的元素.
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</dependency>
</dependencies>
Maven引入本地依赖
有时候 Maven 中央仓库里面没有坐标依赖, 但是我们有 JAR 包. 此时想使用这个 JAR 包, 有如下三种方式 :
① 上传到 maven 中心仓库
- 优点:可以直接在 pom.xml 中引入, 打包部署没有问题
- 缺点:上传复杂, 麻烦( 创建工单, 生成秘钥等等 )
② 上传到 maven 私服
- 优点:下载速度快, maven 聚合项目更适用, 内部使用 deploy 即可, 打包部署没有问题
- 缺点:相比第一种还要麻烦些, 还占用本地服务器资源
③ Maven 引入本地 JAR
可以通过 Maven 引入本地上的 JAR 包.
方式一
引入方式如下 :
<dependency>
<groupId>com.sun.btrace</groupId>
<artifactId>btrace-agent</artifactId>
<version>2.0.2</version>
<type>jar</type>
<scope>system</scope>
<systemPath>C:\btrace-2.0.2\libs\btrace-agent.jar</systemPath>
</dependency>
<dependency>
<groupId>com.sun.btrace</groupId>
<artifactId>btrace-boot</artifactId>
<version>2.0.2</version>
<type>jar</type>
<scope>system</scope>
<systemPath>C:\btrace-2.0.2\libs\btrace-boot.jar</systemPath>
</dependency>
<dependency>
<groupId>com.sun.btrace</groupId>
<artifactId>btrace-client</artifactId>
<version>2.0.2</version>
<type>jar</type>
<scope>system</scope>
<systemPath>C:\btrace-2.0.2\libs\btrace-client.jar</systemPath>
</dependency>
当然对应的位置需要存在 JAR 包的.
方式二
需要在 项目中引入 :
引入方式如下 :
<dependency>
<groupId>com.sun.btrace</groupId>
<artifactId>btrace-agent</artifactId>
<version>2.0.2</version>
<type>jar</type>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/resources/lib/btrace-agent.jar</systemPath>
</dependency>
<dependency>
<groupId>com.sun.btrace</groupId>
<artifactId>btrace-boot</artifactId>
<version>2.0.2</version>
<type>jar</type>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/resources/lib/btrace-boot.jar</systemPath>
</dependency>
<dependency>
<groupId>com.sun.btrace</groupId>
<artifactId>btrace-client</artifactId>
<version>2.0.2</version>
<type>jar</type>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/resources/lib/btrace-client.jar</systemPath>
</dependency>
这种引入方式, 生产环境中, 将本地 jar 包打包到最终得 jar/war 包中时, 需要通过配置加载 resource 文件及打包后加载文件搜索目录.
<build>
<!--打包时,将本地jar打包到jar/war文件中-->
<resources>
<resource>
<!--本地jar得目录-->
<directory>src/main/resources/lib</directory>
<!--打包时, 目标jar存放位置-->
<targetPath>BOOT-INF/lib/</targetPath>
<includes>
<include>**/*.jar</include>
</includes>
</resource>
</resources>
</build>