基础知识
Maven是干什么的?
Maven是一个项目管理工具,包含以下内容:
①一个项目对象模型 (Project Object Model);
②一组标准集合;
③一个项目生命周期(Project Lifecycle);
④一个依赖管理系统(Dependency Management System);
⑤用来运行定义在生命周期阶段(phase)中插件(plugin)目标(goal)的逻辑。;
约定优于配置
通俗理解就是:系统/类库/框架对很多属性都有合理的默认值,除了特殊情况之外,开发者不需要为所有的属性去设置属性值。
举个例子:假如针对Entity,默认DB的表名与类名、列名与类属性名一一对应,那么,开发者基于这个默认的规则去开发即可,如果遇到特殊情况,系统也提供了其他方式去改变这种默认规则。
最后,Maven通过给项目提供明智的默认行为来融合这个概念。
一个普通接口
之前的构建工具,需要你先拿出时间去了解被构建项目的目录结构、项目特点、项目依赖等信息,待了解完之后才能去构建。
这种方式需要花费额外的时间去做,而Maven则避免了这种耗费时间、且无法重复、只能使用一次的构建方式。
基于Maven插件的全局性重用
Maven的功能,主要是由一堆插件来完成的。当你第一次用全新的Maven安装,运行诸如mvn install命令的时候,它会从中央Maven 仓库下载大部分核心Maven插件。
由于Maven是由各个插件来完成具体的功能,例如:测试用的 Surefire插件、编译用的Compiler插件、打JAR包用的JAR插件、用来生成报告的插件、用来向远程服务器发布站点的插件等等。
Maven这样设计的优点有2个:
①插件得到了很好的维护且可以全局的共享,即很多项目共享相同的插件、相同的配置,进而减轻开发人员的工作量。
②插件有官网维护,你可以从远程仓库下载到最新版本。
项目的“概念模型”
一个项目,不仅仅要编写Java文件,把Java文件编译成Class文件,还要包含:项目的许可证是什么、谁开发这个项目、项目依赖于其它什么项目等等信息。
为了合并这些信息,Maven进行了抽象,Maven包含了一组关于软件项目和软件开发的语义规则的平台,该模型包含如下特征:
依赖管理、远程仓库、全局性构建逻辑重用、工具可移植性/集成、便于搜索和过滤构件。
Maven官网地址
首页:http://maven.apache.org/index.html
下载页:http://maven.apache.org/download.cgi
我这里下载的是ZIP包,解压完ZIP包就代表安装完毕。
配置Maven环境变量
新增MAVEN_HOME环境变量,例如:
在PATH中新增MAVEN_HOME环境变量,例如:
查看安装结果
mvn -v
安装目录结构说明
Maven安装完之后,一共才10.7MB,能达到如此苗条的大小是因为Maven的内核被设计成根据需要从远程仓库获取插件和依赖。当你开始使用Maven,它才开始下载插件到本地仓库中,
①LICENSE.txt 包含了Apache Maven的软件许可证;
②NOTICE.txt 包含了一些Maven依赖的类库所需要的通告及权限;
③README.txt包含了一些安装指令;
④bin/目录包含了运行Maven的mvn脚本;
⑤boot/目录包含了一个负责创建Maven运行所需要的类装载器的JAR文件;
⑥conf/目录包含了一个全局的settings.xml文件,该文件用来自定义个人机器上Maven的一些行为,如果需要自定义Maven,更通常的做法是覆写settings.xml文件,每个用户都有对应的这个目录。
⑦lib/目录有了一个包含Maven核心的JAR文件:maven-X.X.X-uber.jar;
本地仓库路径
C:\Users\XXXXXXXX\.m2
设置自定义本地仓库路径
C:\UserSoft\apache-maven-3.6.3\conf\settings.xml
<localRepository/>就是用来自定义本地仓库路径,可以根据个人需求进行自定义设置。
项目对象模型:POM
Maven中,提出了一个项目对象模型(Project Object Model, POM)的概念。该模型既要表达代码的层面,也要表达项目其他属性的层面。
POM其本质是通过XML文件来描述的,该XML文件叫做pom.xml。POM包含了四类描述和配置:
①项目总体信息:包含了一个项目名称、项目URL、发起组织、项目开发者贡献者列表和许可证;
②构建设置:自定义Maven构建的默认行为,比如:更改源码、测试代码的位置、可以添加新的插件、可以将插件目标绑定到生命周期、自定义站点生成参数;
③构建环境:构建环境包含了一些能在不同使用环境中**的profile,比如:针对开发测试环境、生产环境准备2个不同的profile。
④POM关系:一个项目很少孤立存在,它会依赖于其它项目,比如:可能从父项目继承POM设置,它要定义自身的坐标,可能还会包含子模块。
既然提到了继承POM,这里进行POM扩展:
超级POM:
超级POM定义了一组被所有项目共享的默认设置。它是Maven安装的一部分,可以在maven-X.X.X-uber.jar文件中找到pom-X.X.X.xml。
项目对象模型:POM语法
项目版本
一个Maven项目发布版本号用version编码,用来分组和排序发布。Maven中的版本包含以下部分:主版本,次版本,增量版本,限定版本号。对应如下的格式:
<major version>.<minor version>.<incremental version>
-<qualifier>
属性引用
一个POM可以通过一对大括弧和前面一个美元符号来包含对属性的引用。在Maven读取一个POM的时候,它会在载入POM XML的时候替换这些属性的引用。Maven提供了三个隐式的变量,可以分别访问环境变量、POM信息、Maven Settings:
①env变量:暴露了当前操作系统或者shell的环境变量;
②project变量:暴露了POM,你可以使用点标记(.)的路径来引用POM元素的值;
③settings变量:暴露了Maven settings信息,可以使用点标记(.)的路径来引用settings.xml文件中元素的值;
最后,除了这三个隐式的变量,你还可以引用系统属性,任何在Maven POM中和构建profile中自定义的属性组。
项目对象模型:项目依赖
依赖范围
5种依赖范围:
①compile编译范围:compile是默认的范围;如果没有提供一个范围,那该依赖的范围就是编译范围。编译范围依赖在所有的classpath中可用,同时它们也会被打包。
②provided已提供范围:provided依赖只有在当JDK或者一个容器已提供该依赖之后才使用。例如,如果开发了一个web应用,可能在编译classpath中需要可用的Servlet API来编译一个servlet,但是你不会想要在打包好的WAR中包含这个Servlet API;这个Servlet API JAR由你的应用服务器或者servlet容器提供。已提供范围的依赖在编译classpath(不是运行时)可用。它们不是传递性的,也不会被打包。
③runtime运行时范围:runtime依赖在运行和测试系统的时候需要,但在编译的时候不需要。
④test测试范围:test范围依赖在一般的编译和运行时都不需要,它们只有在测试编译和测试运行阶段可用。
⑤system系统范围:基于本地JAR包来编译,因此必须显式的提供一个对于本地系统中JAR文件的路径,Maven也不会在仓库中去寻找它,不推荐使用该方式。
可选依赖
假如你想开发某个功能,而这个功能又依赖于某个第三方lib,但你又不想把这个第三方lib添加到所有工程中,这时,可以使用可选依赖。
依赖版本界限
你并不是必须为依赖声明某个特定的版本,你可以指定一个满足给定依赖的版本范围。例如,可以指定你的项目依赖于JUnit的3.8或以上版本,或者说依赖于JUnit 1.2.10和1.2.14之间的某个版本。你可以使用如下的字符来围绕一个或多个版本号,来实现版本界限:
(, )不包含量词,即大于,或者,小于
[, ]包含量词,即大于等于,或者,小于等于
例如:
[3.8,4.0):大于等于3.8但小于4.0的版本
[,3.8.1]:任意小于等于3.8.1的版本
[4.0,):任意任何大于等于4.0的版本
(,2.0):任意小于2.0的版本
[1.2]:只有版本1.2
传递性依赖
一个传递性依赖就是对于一个依赖的依赖。如果project-a依赖于project-b,而后者接着依赖于project-c,那么project-c就被认为是project-a的传递性依赖。
Maven的部分吸引力是由于它能够管理传递性依赖,并且能够帮助开发者屏蔽掉跟踪所有编译期和运行期依赖的细节。你可以只依赖于一些包如Spring Framework,而不用担心Spring Framework的所有依赖,Maven帮你自动管理了,你不用自己去详细了解配置。
冲突解决
有很多时候你需要排除一个传递性依赖,最后的解决方案无外乎2个:要么整个的排除这个传递性依赖,要么用另外一个提供同样功能的依赖来替代这个传递性依赖。
Maven工程目录结构图
main-java用于放置开发源代码;
main-resources用于放置开发资源文件;
test-java用于放置测试用的源代码,与main-java目录相同;
test-resources用于放置测试资源文件;
target一般是class文件存放路径