四、maven 依赖管理
maven 通过 pom.xml 来进行依赖管理,我们用它来描述项目的依赖属性。可以把它看作是 maven 项目的地图,它描述了 jar 包的坐标、版本以及依赖关系等。如果不确定你想要引入 jar 的坐标怎么写,可以上 maven 中央仓库查询:
- maven 中央仓库:https://mvnrepository.com/
4.1 maven 坐标
maven 的第三方依赖都在 <dependencies>
标签内定义,该标签下的 <dependency>
包裹的内容就是一个 jar
的坐标,如下 pom 就引入了 junit
和 cglib
两个 jar
。
下面就说一下每个坐标的标签都代表什么。
<dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.3.0</version> </dependency> </dependencies>
- dependencies
在 dependencies 标签中,添加项目需要的 jar 所对应的 maven 坐标。
- dependency
一个 dependency 标签表示一个坐标,也就是一个 jar,在 pom 中引入一个 jar 可以这样写:
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency>
- groupId
公司、团体、个人开发者的唯一标识符,maven 约束它以创建这个项目的组织名称的逆向域名开头,比如开发者的域名是 nasus.com
那他的唯一标识符就是 com.nasus
。
<!--团体唯一标识符--> <groupId>com.nasus</groupId>
- artifactId
项目唯一标识符,一个组织可能有多个项目,为了方便 maven 引入,maven 约定以项目名称命名该标识符,比如我开发的 maven-test 项目。
<!--项目唯一标识符--> <artifactId>maven-test</artifactId>
- version
项目的版本。一个项目,可能会有多个版本。如果是正在开发的项目,我们可以给版本号加上一个 SNAPSHOT,表示这是一个快照版本。
什么是快照?
对于版本,如果 maven
以前下载过指定的版本文件,比如说 maven-test:1.0
,maven
将不会再从仓库下载新的可用的 1.0
文件。若要下载更新的代码,maven-test
的版本需要升到 1.1
。
快照是一种特殊的版本,指定了某个当前的开发进度的副本。不同于常规的版本,
maven
每次构建都会在远程仓库中检查新的快照。我们自己的模块依赖了同事开发的模块,正常来说,同事会每次发布更新代码的快照到仓库中。
新建项目的默认版本号就是快照版,比如上面用 maven 命令新建的 maven-test 项目:
4.2 依赖范围
- scope
maven 项目不同的阶段引入到 classpath 中的依赖是不同的,例如,编译时,maven 会将与编译相关的依赖引入 classpath 中,测试时,maven 会将测试相关的的依赖引入到 classpath 中,运行时,maven 会将与运行相关的依赖引入 classpath 中,而依赖范围就是用来控制依赖于这三种 classpath 的关系。 如下图所示:
scope 表示依赖的范围,它有 compile(编译阶段)、test(测试阶段)、provided(供应阶段)、runtime(运行阶段)、system(系统阶段)、import(导入阶段)
六个可选值。其中 compile
是默认的。system
和 import
用得少,不详细讲。
不同依赖的适用范围不一样,举几个最典型的栗子:
范围 | 编译有效 | 测试有效 | 运行时有效 | 打包有效 | 示例 |
compile | √ | √ | √ | √ | spring-core |
test | × | √ | × | × | junit |
provided | √ | √ | × | × | javax.servlet-api |
runtime | × | √ | √ | √ | JDBC 驱动 |
- compile: 编译依赖范围。如果没有指定,就会默认使用该依赖范围。使用此依赖范围的 Maven 依赖,对于编译、供应、测试、运行四种 classpath 都有效。比如
spring-core
- provided: 已提供依赖范围。使用此依赖范围的 Maven 依赖,对于 编译和测试 classpath 有效,但在运行时无效。典型的例子是
servlet-api
编译和测试项目的时候需要该依赖,但在运行项目的时候,由于容器已经提供,就不需要maven
重复地引入一遍:
<dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency>
- test: 单元测试依赖范围,只在测试的时候生效,所以可以设置它的 scope 为 test,这样,当项目打包发布时,单元测试的依赖就不会跟着发布。比如:
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency>
- runtime: 运行时依赖范围。对于测试和运行 classpath 有效,但在编译主代码时无效。典型的例子是 JDBC 驱动实现,项目主代码的编译只需要 JDK 提供的 JDBC 接口,只有在执行测试或者运行项目的时候才需要实现上述接口的具体 JDBC 驱动。所以,我们使用 JDBD 驱动时,可以定义成以下样例:
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.12</version> <scope>runtime</csope> </dependency>
4.3 排除依赖
如下 xml,原来的定义中已引入 commons-net
依赖,而 hermes-ftp
中又依赖了 commons-net
,为避免版本冲突,我们可以排除 hermes-ftp
中的 commons-net
依赖。
<dependency> <groupId>commons-net</groupId> <artifactId>commons-net</artifactId> <version>3.6</version> </dependency> <dependency> <groupId>com.nasus.greece.jupiter</groupId> <artifactId>hermes-ftp</artifactId> <version>1.1.0-SNAPSHOT</version> <!--排除 commons-net 依赖--> <exclusions> <exclusion> <artifactId>commons-net</artifactId> <groupId>commons-net</groupId> </exclusion> </exclusions> </dependency>
4.4 依赖传递
假设有如下项目关系:WebMavenDemo
项目依赖 JavaMavenService1
,JavaMavenService1
项目依赖 JavaMavenService2
。
pom.xml 文件配置好依赖关系后,必须首先 mvn install 后,依赖的 jar 包才能使用。比如:
WebMavenDemo
的pom.xml
文件想能编译通过,JavaMavenService1
必须mvn install
JavaMavenService
的pom.xml
文件想能编译通过,JavaMavenService2
必须mvn install
传递性:
假设我们现在 JavaMavenService2
增加 spring-core
,那就会发现 WebMavenDemo
和 JavaMavenService1
也会自动的增加了这个 jar
包,这就是依赖的传递性。
注意:非
compile
范围的依赖是不能传递的。
- 来源:cnblogs.com/hzg110/p/6936101.html
4.5 统一管理依赖版本
在上面介绍 pom 文件时,我们讲过 properties
标签,它还有一个作用就是限定依赖的 jar 包版本,它常用在父项目中指定版本号,那么子项目用到该包就避免了版本不一致造成的依赖冲突,它的写法是这样的:
五、build 配置
maven 打 war 包时,可能需要一些额外的配置,请参看以下 xml 文件:
<build> <!-- 项目的名字 --> <finalName>maven-test</finalName> <!-- 描述项目中资源的位置 --> <resources> <!-- 自定义资源1 --> <resource> <!-- 资源目录 --> <directory>src/main/java</directory> <!-- 包括哪些文件参与打包 --> <includes> <include>**/*.xml</include> </includes> <!-- 排除哪些文件不参与打包 --> <excludes> <exclude>**/*.txt</exclude> <exclude>**/*.doc</exclude> </excludes> </resource> </resources> <!-- 设置构建时候的插件 --> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>2.1</version> <configuration> <!-- 源代码编译版本 --> <source>1.8</source> <!-- 目标平台编译版本 --> <target>1.8</target> </configuration> </plugin> <!-- 资源插件(资源的插件) --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <version>2.1</version> <executions> <execution> <phase>compile</phase> </execution> </executions> <configuration> <encoding>UTF-8</encoding> </configuration> </plugin> <!-- war插件(将项目打成war包) --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>2.1</version> <configuration> <!-- war包名字 --> <warName>maven-test</warName> </configuration> </plugin> </plugins> </build>
六、使用 idea 搭建 maven 聚合工程
这个网上很多资料,不讲了。留个链接。
- idea 搭建 maven 聚合工程参考:https://www.cnblogs.com/limn/p/9363416.html