No Regrets.

maven的基础详讲

Posted on By Marin



Maven

Maven是一个自动化构建工具,主要服务于java平台的项目构建和依赖管理;

为什么要使用maven?
1、降低一个项目的臃肿程度,大量地导入jar包会让整个项目看起来非常庞大;
2、自动导入依赖。我们在开发中很多jar包都存在一大堆的依赖包,比如spring-core依赖commons-logging,maven会帮助我们自动导入相关依赖;
3、避免不规范的导入所带来的错误。每个知名的第三方库都会提供相关的maven依赖信息,存储在中央仓库,来供我们下载到本地仓库,这种官方提供的信息代表着规范性,而我们平时下载一些jar包不是通过官网下载可能中间会被别人做过一些修改,这种修改会影响原本jar包的规范性,可能在项目中引用这些jar包就会带来一些未知的错误;
4、统一的版本控制,对于spring等一套框架所需要的jar包,我们一般需要引入相同版本的jar包,maven能通过pom配置为我们进行统一的版本管理;
5、更好的协同开发。通过maven进行项目构建和管理,能让我们把项目拆分为多个工程进行开发,同时对于公用的模板还能进行多方的依赖调用,大大加快了开发的效率;
6、自动化构建。maven的自动化构建大大提升了我们的开发测试效率,我们可以一键完成从编译到部署的一系列的动作;

怎么使用maven?
maven的核心程序中仅仅定义了抽象的生命周期,而具体的操作则是由maven的插件来完成的,但maven的插件并不包含在maven的核心程序中,所以首次使用需要联网下载;

目录结构

maven具有一个约定好的目录结构,这也是maven实现自动化构建的基础,只有按照maven的约定进行项目构建之后maven才能到相应的位置执行对应的操作;现在javaEE开发领域普遍认同的一个观点‘:约定>配置>编码;


构建的过程

1、清理:删除之前的编译结果,为重新编译做好准备;(mvn clean//清除目标木兰路中的所有生成结果——也就是删除target目录下的所有内容)
2、编译:将java源程序编译为字节码文件;(mvn compile//编译源代码;mvn test-compile//编译测试代码)
3、测试:针对项目中的关键点进行测试,确保项目在迭代开发过程中关键点的正确性;(mvn test//运行应用程序中的单元测试)
4、报告:在每一次测试后以标准的格式记录和展示测试结果;(没有相关命令,在测试命令中会在打印出相关信息)
5、打包:将一个包括诸多文件的工程封装为一个压缩文件用于安装或部署。java工程对应jar包,web工程对用war包;(mvn package//依据项目生成对应的包)
6、安装:在maven环境下特指将打包的结果——jar包或war包安装到本地仓库中;(mvn install//将项目安装到本地仓库中)
7、部署:将打包的结果部署到远程仓库或将war包部署到服务器上运行;(mvn deploy)

POM

Project Object Model:项目对象模型。将java工程的相关信息封装为对象作为便于操作和管理的模型;maven的核心配置就是pom.xml,学习maven其实就是学习pom.xml的配置;

坐标

maven的坐标是使用三个向量在maven的仓库中唯一的确定一个maven工程。
1、groupid:公司或组织的域名倒序+当前项目名称;
2、artifactid:当前项目的模块名称;
3、version:当前模块的版本;

这就是我们在配置文件中配置的相关依赖信息,其在仓库中对应相关的jar包依赖;比如:

<dependency><br>
<groupid>com.mzt.maven</groupid><br>
<artifactid>Hello</artifactid><br>
<version>0.0.1-SNAPSHOT</version><br>
</dependency><br><br>

这个配置信息在本地仓库中对应的jar包为:本地仓库目录路径/com/mzt/maven/Hello/0.0.1-SNAPSHOT/Hello-0.0.1-SNAPSHOT.jar;

依赖管理

依赖管理是maven中最关键的部分;
当Ajar包中用到了Bjar包中的某些类时,A就对B产生了依赖;

依赖的范围:
在依赖配置中加入一个scope便签来进行依赖范围的配置,依赖的范围包括compile,test,provided三个;
从项目结构角度理解compile和test的区别:


从开发和运行两个不同阶段理解compile和provided的区别:


有效性的总结:


依赖的传递性:
工程存在如下关系:A依赖B,B依赖C,那么A能否使用C呢?


依赖的排除:
也就是排除某一方面的依赖传递,解决方案是通过修改配置文件,在对应的依赖配置中加入如下标签内容:

<exclusions><br>
	<exclusion><br>
		<groupid>XXX</groupid><br>
		<aritfactid>XXX</aritfactid><br>
	</exclusion><br>
</exclusions><br><br>

统一依赖包的版本管理:
通过配置:
1、统一声明版本号:

<properties><br>
	<com.mzt.spring.version>4.1.1.RELEASE</com.mzt.spring.version><br>
</properties><br>

这里面com.mzt.spring.version为自定义标签;
2、引用前面声明的版本号:

<dependency><br>
	<groupid>org.springframework</groupid><br>
	<artifactid>spring-core</artifactid><br>
	<version>${com.mzt.spring.version}</version><br>
</dependency><br><br>

依赖的原则:
目的是解决jar包冲突;
原则一:路径最短者优先;


原则二:路径相同时先声明者优先;(指在配置文件中声明依赖关系的顺序)


仓库管理

仓库的分类:
本地仓库:为当前本机电脑上的所有maven工程服务。(默认的本地仓库在本机家目录下的/.m2/repository;但可以通过修改maven本地程序中conf下的setting.xml中的localrepository,指定我们想要的本地仓库路径)
远程仓库:1、私服:架设在当前局域网环境下,为局域网范围内的所有maven工程服务;2、中央仓库:架设在Internet上,为全世界所有的maven工程服务;3、中央仓库的镜像:架设在各个大洲,为中央仓库分担流量,减轻中央仓库的压力,同时更快的响应用户请求;


仓库中的文件:1、maven的插件;2、我们自己开发的项目的模块;3、第三方框架或工具的jar包;

maven中的仓库按稳定性又分为两种,snapshot快照仓库和release发布仓库。snapshot快照仓库用于保存开发过程中的不稳定版 本,release正式仓库则是用来保存稳定的发行版本。定义一个组件/模块为快照版本,只需要在pom文件中在该模块的版本号后加上-SNAPSHOT即可(注意这里必须是大写)。release版本不允许修改,每次进行release版本修改,发布必须提升版本号。而snapshot一般是开发过程中的迭代版本,snapshot更新后,引用的项目可以不修改版本号自动下载构建。

生命周期

maven生命周期定义了各个构建环节的执行顺序,有了这个清单,maven就可以自动化的执行构建命令;

maven有三套相互独立的生命周期:
1、Clean Lifecycle在进行真正的构建之前进行一些清理工作;
包括三个阶段:
1、pre-clean 执行一些需要在clean之前完成的工作;
2、clean移除所有上一次构建生成的文件;
3、post-clean执行一些需要在clean之后立刻完成的工作;

2、Default Lifecycle构建的核心部分,编译,测试,打包,安装,部署等等。
default生命周期是maven生命周期中最重要的一个,绝大部分工作都发生在这个生命周期中;
包括以下比较重要和常用的阶段:
validate
generate-sources
process-sources
generate-resources
process-resources复制并处理资源文件,至目标目录,准备打包;
compile编译项目中的源代码;
process-classes
generate-tst-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将最终的包复制到远程的仓库,以让其他开发人员与项目共享或部署到服务器上运行;
3、Site Lifecycle生成项目报告,站点,发布站点;
包括四个阶段:
1、pre-site执行一些需要在生成站点文档之前完成的工作;
2、site生成项目的站点文档;
3、post-site执行一些需要在生成站点文档之后完成的工作,并且为部署做准备;
4、site-deplov将生成的站点文档部署在特定的服务器上;


maven的生命周期存在这样一个特性:运行任何一个阶段的时候,它前面的所有阶段都会被运行,比如我们运行mvn install的时候,代码也会被编译、测试和打包;这也是maven为什么能够自动执行构建的原因;

maven的插件机制是完全依赖maven的生命周期的;

插件和目标

maven的核心程序仅仅定义了抽象的生命周期,具体的任务都是交由插件完成的;
每个插件都能实现多个功能,每个功能就是一个插件目标;
maven的生命周期与插件目标相互绑定,以完成某个具体的构建任务。比如compile是插件maven-compiler-plugin的一个目标,test-compile也是插件maven-compiler-plugin的一个目标,而pre-clean是插件maven-clean-plugin的一个目标

继承

继承机制产生的原因是因为非compile范围的依赖信息是不能再“依赖链”中传递的,所以有需要的工程只能单独配置;
这时如果我们需要去升级我们单元测试的版本,那么就需要去手动修改各个工程的版本,这样子的不可取的;
使用继承机制就是将这样的依赖信息统一提取到父工程模块中进行统一管理;

实现步骤:
1、创建父工程:和创建普通java工程操作一致,唯一需要注意的是:打包方式要设置为pom
2、在子工程中引用父工程:

<parent><br>
	<groupid>..</groupid>//父工程的坐标<br>
	<artifactid>..</artifactid><br>
	<version>...</version><br>
	<relativePath>从当前目录到父工程的pom.xml文件的相对路径</relativepath><br>
</parent><br>

3、在父工程中管理依赖:

<dependencyManagement><br>
	<dependencies><br>
		<dependency><br>
			<groupid>xxx</groupid><br>
.......
<br>

4、在子项目中直接指定需要的依赖,删除范围和版本号

聚合

将多个工程拆分为模块后,需要手动逐个安装到仓库后依赖才能生效,修改源码狗也需要逐个手动进行clean操作,使用聚合就可以批量进行maven工程的安装、清理工作;

在总的聚合工程中进行配置(不一定是要父工程),指定模块工程的相对路径即可

<modules>
	<module>../Hello</module>
	<module>../HelloWorld</module>
</modules>

扩展

maven的库

maven的依赖查询

其他maven常用命令:
mvn -v:查看maven版本
mvn archetype:create:创建maven项目
mvn archetype:generate :创建项目架构
mvn dependency:list:查看已解析依赖
mvn dependency:tree :查看依赖树
mvn dependency:analyze:查看依赖的工具
mvn help:system:从中央仓库下载文件到本地仓库
mvn help:active-profiles:查看当前激活的profiles
mvn help:all-profiles:查看所有的profiles
mvn help:effective -pom:查看完整的pom信息



有Marin的地方就有你的收获