基础知识

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文件存放路径