Maven的目录结构,POM,坐标,仓库,依赖,生命周期,继承,聚合分别是什么呢?
Maven的目录结构
这一部分的内容在我的上一篇《快速上手Maven》已经讲过,在这就不在过多赘述。
HelloMaven:根目录(工程名)
src:源码
pom.xml:Maven工程的核心配置文件
main:存放主程序
test:存放测试程序
java:存放java源文件
resources:存放框架或者其它工具的配置文件
POM
[1]含义:Project Object Model 项目对象模型,类似与DOM Document Object Model 文档对象模型
[2]pom.xml对于Maven工程是核心的配置文件,与构建过程相关的一切设置都在这个文件中进行配置。重要程度相当于web.xml对于动态Web工程。
坐标
- 在Maven中坐标是使用三个向量在仓库中唯一定位一个Maven工程
[1]groupId:公司或者组织的唯一标志,一般用公司或组织域名倒序+项目名
[2]artifactId:模块名,项目的唯一ID,一个groupId下面可能多个项目,就是靠artifactId来区分的<groupId>com.xiezhenyu.maven</groupId>
[3]version:版本号<artifactId>HelloMaven</artifactId>
<version>1.0</version>
- Maven坐标与仓库中路径的对应关系
如com.xiezhenyu.maven,maven会将该项目打成的jar包放本地仓库路径:/com/xiezhenyu/maven-1.0.jar。我们自己的 Maven 工程必须执行安装操作才会进入仓库,安装的命令是:mvn install。
仓库
- 仓库的分类
[1]本地仓库:为当前本机电脑上所有的Maven工程服务
[2]远程仓库:远程仓库分为私服、中央仓库、中央镜像仓库。私服:架设在当前局域网环境下,为当前局域网范围内的所有Maven工程服务;中央仓库:架设在Internet上,为全世界所有的Maven工程服务;中央仓库镜像:架设在各个大洲上,为中央仓库分担流量。减轻中央仓库的压力,同时更快的响应用户请求。
其中仓库的关系可以参照下图:
- 仓库中的文件(仓库中保存的内容)
[1]Maven自身所需要的插件
[2]第三方框架或工具的jar包
[3]我们自己开发的Maven工程
依赖
-
概念
当 A jar 包用到了 B jar 包中的某些类时,A 就对 B 产生了依赖,这是概念上的描述。Maven解析依赖信息时会到仓库中查找被依赖的jar包。 如果要使用我们自己开发的jar包,要使用mvn install
命令安装后就可以进入仓库。 -
依赖的范围
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency>
在上面
<scope>test</scope>
就是描述依赖的范围,其值可以有
其文字描述为:compile范围依赖
※对主程序是否有效:有效
※对测试程序是否有效:有效
※是否参与打包:参与
※是否参与部署:参与
※典型例子:spring-coretest范围依赖
※对主程序是否有效:无效
※对测试程序是否有效:有效
※是否参与打包:不参与
※是否参与部署:不参与
※典型例子:Junit从开发和运行这两个阶段理解compile 和 provided 的区别
compile围依赖
provided 范围依赖
-
依赖的传递性
比如A.jar依赖B.jar,B.jar依赖C.jar,A.jar能否使用C.jar呢?这时就需要看B.jar依赖C.jar的范围是不是compile范围的依赖。这就说明,C.jar只是给B.jar单独使用的。 -
依赖的排除
如果我们当前工程中引入了一个依赖是A.jar,而A.jar又依赖了B.jar,那么Maven会自动将A依赖的B引入当前工程,但是个别情况下B.jar有可能是一个不稳定版本,或对当前工程有不良影响。这时我们可以在引入A.jar的时候将B.jar排除。
①情景
②配置方式<dependency> <groupId>com.xiezhenyu.maven</groupId> <artifactId>HelloMaven</artifactId> <version>1.0</version> <type>jar</type> <scope>compile</scope> <!-- 配置需要排除的依赖信息 --> <exclusions> <exclusion> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> </exclusion> </exclusions> </dependency>
③排除后的结果
-
依赖的原则,解决jar包冲突
①路径最短者优先
会根据jar包的路径最短的原则依赖jar包
②路径相同时先声明者优先,先生命指的是dependency标签声明的顺序。
-
统一管理所依赖的版本
对同一个框架的一组jar包最好使用相同的版本。为了方便升级架构,可以将jar包的版本信息统一提取出来。
①统一声明版本号(其中 jackson.version 部分是自定义标签。)<properties> <jackson.version>2.9.6</jackson.version> </properties>
②引用前面声明的版本号 (在这里就会统一引用声明好的版本号)
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>${jackson.version}</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>${jackson.version}</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>${jackson.version}</version> </dependency>
③其实properties标签配合自定义标签声明数据的配置并不是只能用于声明依赖的版本号。凡是需要统一声明后再引用的场合都可以使用。
生命周期
- 各个构建环节执行的顺序:不能打乱顺序,必须按照既定的正确顺序来执行。
- Maven的核心程序中定义了抽象的生命周期,生命周期中各个阶段的具体任务是由插件来完成的。
- Maven核心程序为了更好的实现自动化构建,按照这一特点执行生命周期中各个阶段:不论现在要执行生命周期中的哪一阶段,都是从这个生命周期最初的位置开始执行。
- Maven有三套相互独立的生命周期,分别是:
①Clean Lifecycle 在进行真正的构建之前进行一些清理工作。
②Default Lifecycle 构建的核心部分,编译、测试、打包、安装、部署等等。
③Site Lifecycle 生成项目报告,站点,发布站点。
他们相互独立。也可以直接运行 mvn clean install site 运行所有这三套生命周期。每套生命周期都由一组阶段(Phase)组成,我们平时在命令行输入的命令总会对应于一个特定的阶段。比如,运行 mvn clean,这个 clean 是 Clean 生命周期的一个阶段。有 Clean 生命周期,也有 clean 阶段。 - Clean声明周期
①pre-clean 执行一些需要在clean之前完成的工作
②clean 移除所有上一次构建生成的文件
③post-clean 执行一些需要在clean 之后立刻完成的工作 - Default声明周期
Default 生命周期是 Maven 生命周期中最重要的一个,绝大部分工作都发生在这个生命周期中。这里标红一些比较重要和常用的阶段:
validate(校验) 校验项目是否正确并且所有必要的信息可以完成项目的构建过程。
initialize(初始化) 初始化构建状态,比如设置属性值。
generate-sources(生成源代码) 生成包含在编译阶段中的任何源代码。
process-sources(处理源代码) 处理源代码,比如说,过滤任意值。
generate-resources(生成资源文件) 生成将会包含在项目包中的资源文件。
process-resources (处理资源文件)
复制和处理资源到目标目录,为打包阶段最好准备。
compile(编译)
编译项目的源代码。
process-classes(处理类文件) 处理编译生成的文件,比如说对Java class文件做字节码改善优化。
generate-test-sources(生成测试源代码) 生成包含在编译阶段中的任何测试源代码。
process-test-sources
(处理测试源代码) 处理测试源代码,比如说,过滤任意值。
generate-test-resources(生成测试资源文件) 为测试创建资源文件。
process-test-resources(处理测试资源文件) 复制和处理测试资源到目标目录。
test-compile
(编译测试源码) 编译测试源代码到测试目标目录.
process-test-classes(处理测试类文件) 处理测试源码编译生成的文件。
test(测试)
使用合适的单元测试框架运行测试(Juint是其中之一)。
prepare-package(准备打包) 在实际打包之前,执行任何的必要的操作为打包做准备。
package(打包)
将编译后的代码打包成可分发格式的文件,比如JAR、WAR或者EAR文件。
pre-integration-test(集成测试前) 在执行集成测试前进行必要的动作。比如说,搭建需要的环境。
integration-test(集成测试) 处理和部署项目到可以运行集成测试环境中。
post-integration-test(集成测试后) 在执行集成测试完成后进行必要的动作。比如说,清理集成测试环境。
verify (验证) 运行任意的检查来验证项目包有效且达到质量标准。
install(安装)
安装项目包到本地仓库,这样项目包可以用作其他本地项目的依赖。
deploy(部署)
将最终的项目包复制到远程仓库中与其他开发者和项目共享。 - Site生命周期
①pre-site 执行一些需要在生成站点文档之前完成的工作
②site 生成项目的站点文档
③post-site 执行一些需要在生成站点文档之后完成的工作,并且为部署做准备
④site-deploy 将生成的站点文档部署到特定的服务器上 - 插件和目标
①生命周期的各个阶段仅仅定义了要执行的任务是生命
②各个阶段和插件的目标是对应的
③相似的目标由特定的插件来完成
例如:compile 就是插件 maven-compiler-plugin 的一个目标;pre-clean 是插件 maven-clean-plugin 的一个目标。
继承
- 现状
Hello依赖的Junit:4.0
HelloFriend依赖的Junit:4.0
MakeFriends依赖的Junit:4.9
由于test范围的依赖不能传递,所以必然会分散在各个模块工程中,很容易造成版本不一致。 - 需求:统一管理各个模块工程中对Junit依赖的版本。
- 解决思路:将Junit依赖统一提取到“父”工程中,在子工程中声明Junit依赖是不指定版本,以父工程中统一设定的为准。同时也便于修改。
- 操作步骤:
①创建一个Maven工程作为父工程。注意:打包方式为pom
②在子工程中声明对父工程的引用<groupId>com.xiezhenyu.maven</groupId> <artifactId>Parent</artifactId> <version>1.0</version> <packaging>pom</packaging>
③将子工程的坐标中与父工程坐标中重复的内容删除<!-- 在子过程中声明父工程 --> <parent> <groupId>com.xiezhenyu.maven</groupId> <artifactId>Parent</artifactId> <version>1.0</version> <!-- 以当前工程的pom.xml文件为基准的父工程pom.xml文件的相对路径 --> <relativePath></relativePath> </parent>
④在父工程中统一管理Junit的依赖
⑤在子工程中删除Junit依赖的版本号部分<!-- 配置依赖的管理 --> <dependencyManagement> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> </dependencies> </dependencyManagement>
注意:配置集成后,执行安装命令时要先安装父工程。
聚合
如果我们写了很多模块,在我们安装的时候就需要我们一个个安装,这样就整加了工作量,而聚合可以解决这个问题。
- 聚合作用:一键安装各个模块工程。
- 配置方式:在一个“总的聚合工程”中配置各个参与聚合的模块(比如说在父工程配置)
<!-- 配置聚合 --> <modules> <!-- 配置一起安装的各个工程 --> <module>../Hello</module> <module>../HelloFriend</module> <module>../MakeFriends</module> </modules>
- 使用方式:在聚合工程的pom.xml 上点右键->run as->maven install