Maven这个单词来自于意第绪语(犹太语),意为知识的积累,最初在Jakata Turbine项目中用来简化构建过程。当时有一些项目(有各自Ant build文件),仅有细微的差别,而JAR文件都由CVS来维护。于是希望有一种标准化的方式构建项目,一个清晰的方式定义项目的组成,一个容易的方式发布项目的信息,以及一种简单的方式在多个项目中共享JARs。于是maven诞生了。
在我们的日常项目中,maven不仅是一个依赖管理工具,有效的帮我们管理项目中需要使用到的各种依赖,也是一个项目构建工具,可以通过其内置的项目模板(也称为骨架 archetype),构建常规的项目(jar war等)。使用的maven项目的对象模型(pom-project object model),可以通过一小段描述信息来管理项目的构建,报告和文档的管理。
这里举个生活中的例子,比如此时的你想要配一台主机来玩游戏,那么你需要去选购组成这个主机的各种配件,进而需要去了解各种配件的性能,配件之间的兼容性,组装好后还需要自己装操作系统和驱动程序,这使得不熟悉组装电脑主机的你需要花费大量的时间,最后的结果还可能是你的主机运行不稳定,经常蓝屏。在这个时候突然有个人告诉你,你可以去某个知名的电商平台,你可以浏览一下主流的机型,选择了你需要的配置,然后下单、付款。接着PC供应商帮我组装电脑、安装操作系统和驱动程序,物流公司将电脑送到我的家里,你接上显示器、电源、鼠标和键盘就能直接使用了。这为你节省了大量时间,而且这台电脑十分稳定,商家在把电脑发送给你之前已经进行了很好的测试。这难道不香吗?
在日常的团队开发中,这种找配件组装"主机"的方式,显得更杂乱无序,既无法有效的确保依赖之间的兼容性,又不能保证资源的重用型,且无法摆脱对代码工具的依赖,对于大型项目的开发,框架的整合,依赖的管理带来了很大的困扰。而使用maven这个强大的依赖管理,项目工具,你的问题将迎刃而解,它将帮我们完成,自动关联,拉取依赖,升级框架,依赖有效管理,自动测试,打包部署等,所以我们要说maven :yes。
前往https://maven.apache.org/download.cgi下载最新版的Maven程序
然后将文件解压到你自己想要存放的目录下(如D:\Program Files (x86)\apache-maven-3.6.1):
环境变量配置:
新建环境变量MAVEN_HOME,赋值D:\Program Files (x86)\apache-maven-3.6.1
编辑环境变量Path,追加%MAVEN_HOME%\bin;
至此,maven已经完成了安装,我们可以通过DOS命令检查一下我们是否安装成功:
maven仓库引用结构
本地仓库(local)->自己在磁盘创建的用以存放资源的文件夹;
私服镜像(aliyun)->常使用国内资源镜像,提升资源拉取速度;
中央仓库central->maven官方仓库资源。
maven资源拉取方式
在maven的pom配置文件中国配置项目所需的依赖,在项目保存时,maven将自动通过你配置的坐标路径去拉取依赖资源,首先会去扫描本地仓库,若有,直接获取,若无,将会前往所配置的私服镜像去拉取相关的依赖资源。
仓库配置
进入你的maven文件安装目录,找到conf配置文件夹,修改setting.xml,修改本地仓库位置
修改镜像源,拉取国内资源的路径配置 setting.xml
alimaven
aliyun maven
http://maven.aliyun.com/nexus/content/groups/public/
central
通过以上步骤,已经完成了maven的安装与简单配置。
maven comand
// 编译源代码
mvn compile
// 运行测试
mvn test
// 项目打包
mvn package
// 清除产生的项目
mvn clean
//项目打包时跳过测试
mvn package -Dmaven.test.skip=ture
maven pointer
//定义当前 Maven 项目从属的实际项目,表述形式同 Java 包名的表述方式类似,通常与域名反向一一对应
groupId
//定义实际项目中的一个 Maven 项目(实际项目中的一个模块),表述形式为当前项目名
artifactId
//定义 Maven 当前所处的版本
version
//定义 Maven 项目的打包方式
packaging
//定义构件输出的附属构件
classifier
//依赖描述:
type: 依赖的类型
scope: 依赖的范围
optional: 标记依赖是否可选
exclusions: 用来排除传递性依赖
简单的java se项目 jar
# 在你的磁盘中新建文件加,用以存放maven创建的项目 然后cmd 切换到你的文件夹路径,执行以下代码片段
# 生成java se 项目
mvn archetype:generate -DarchetypeCatalog=internal -DgroupId=com.zglt.build -DartifactId=demo
# cmd 切换到你的项目路径下即在pom.xml的目录下运行以下代码
mvn clean compile exec:java -Dexec.mainClass="com.zglt.build.App"
# 将项目程序打包,用以发布
mvn package
maven构建普通项目的结构
└─src classPath项目源码根目录
├─main 主要
│ ├─java java源码
│ │ └─com
│ │ └─zglt
│ │ └─build com.zglt.build包名
│ └─resources 资源: 配置文件(约定优于配置)
└─test 用于单元测试的相关包
└─java
└─com
└─zglt
└─build
pom.xml 项目对象模型配置(依赖管理等)
pom.xml配置
4.0.0
com.zglt.build
demo
1.0-SNAPSHOT
jar
demo
http://maven.apache.org
UTF-8
junit
junit
3.8.1
test
maven基于构建生命周期的中心概念,定义了项目构建的每一个阶段过程,对于构建项目的人员,这意味着只需要学习一小堆命令即可构建任何Maven项目,POM将确保他们获得所需的结果。
检验
(validate) - 验证项目是否正确,所有必要的信息是否可用;
初始化
(initialize)项目文件配置初始化;
编译
(compile) - 编译项目的源代码;
单元测试
(test) - 使用合适的单元测试框架测试编译的源代码(这些测试不应该要求代码被打包或部署)
打包
(package) - 采用编译的代码,并以其可分配格式(如JAR)进行打包;
集成测试
(verify) - 对集成测试的结果执行任何检查,以确保满足质量标准;
安装
(install) - 将软件包安装到本地存储库中,用作本地其他项目的依赖项;
部署
(deploy) - 在构建环境中完成,将最终的包复制到远程存储库以与其他开发人员和项目共享。
a.compile 默认的范围,编译测试运行都有效;
b.provided 编译和测试时有效,最后是在运行的时候不会被加入,如servlet api;
c.runtime 在测试和运行时有效,如MYSQL JDBC DRIVER;
d.test 在测试时有效,如junit;
e. system 与本机系统相关联,编译/测试/运行时有效;
f. import 导入的范围,它只在使用dependencyManagement中,表示从其他pom中导入dependecy的配置。
在maven中,依赖是可以传递的,就是说假设存在三个项目,分别是项目c,项目b以及项目a,假设a依赖于b,b依赖于c,那么我们可以根据Maven项目依赖的特征不难推出项目a也依赖于c(只有编译时和运行时依赖是传递的),所谓的传递依赖,简单的说,a的运行需要b的存在,那么a依赖于b,而b的运行又需要c的存在,那么b依赖于c,根据需求传递,那么可以推出a的运行需要c的存在。
同理在一个项目中,既然存在依赖之间的传递,那么当依赖发生冲突的时候,maven又是怎么进行依赖管理的呢,我们举例说明什么是依赖冲突,假设有如下的依赖树:
最短路径原则
A
| B
| | | C
| C
可以看出项目A存在有2个直接的依赖B,C和一个间接的依赖C,此时对于项目A来说,将会有两个版本的C,从而产生版本冲突,也就是是所说的依赖冲突,maven在解决如下冲突时,使用最短路径原则,亦即这里的A项目将直接依赖最短路径的C。
优先声明原则
A
| B
| | | C 1.0 优先
| E
| | | C 2.0
可以看出项目A存在有2个直接的依赖B,E和2个间接的依赖C,此时对于项目A来说,将会有两个版本的C且路径距离相同,从而产生依赖冲突,maven在解决如下冲突时,使用优先声明原则,亦即这里的A项目将直接依赖于优先在pom中声明的C 1.0版本。