Maven
Maven介绍
Maven 翻译为"专家"、"内行",是 Apache 下的一个纯 Java 开发的开源项目。基于项目对象模型(缩写:POM)概念,Maven利用一个中央信息片断能管理一个项目的构建、报告和文档等步骤。
Maven 是一个项目管理工具,可以对 Java 项目进行构建、依赖管理。
Maven 也可被用于构建和管理各种项目,例如 C#,Ruby,Scala 和其他语言编写的项目。Maven 曾是 Jakarta 项目的子项目,现为由 Apache 软件基金会主持的独立 Apache 项目。
maven的功能:
- 构建、文档生成、报告、依赖、SCMs、发布、分发、邮件列表
- 打包文件,形成jar文件或者war文件。
Maven的构建
构建是一些步骤的统称,例如项目代码的编译、测试、运行、打包、部署等。
maven支持的构建包括:
- 清理clean:把之前项目编译的东西删除掉,为新的编译代码作准备。
- 编译compile:把程序代码编译成可执行文件,java-class文件。批量的,可以同时将多个文件编译成class。
- 测试test:maven可以执行测试程序代码,验证功能是否正确,批量的,同时测试很多功能。
- 报告:生成的测试结果文件,测试报告。
- 打包package:把项目中所有的class文件、配置文件等所有资源放到一个压缩文件中。java程序通常是jar扩展名的,对于web应用扩展名通常是.war。
- 安装install:把步骤5中生成的文件安装到本机仓库。
- 部署deploy
Maven的安装
-
maven官网下载安装文件。Maven官网
-
解压缩安装包,到自己指定的非中文目录。
-
设置 Maven 环境变量
添加环境变量 MAVEN_HOME:
右键 "计算机",选择 "属性",之后点击 "高级系统设置",点击"环境变量",来设置环境变量,有以下系统变量需要配置:新建系统变量 MAVEN_HOME,变量值:E:\Maven\apache-maven-3.3.9

编辑系统变量 Path,添加变量值:;%MAVEN_HOME%\bin

-
验证是否安装成功。打开终端输入mvn -v。正常会输出Maven版本信息、java版本信息和系统信息。如下:
C:\Users\lowell>mvn -v Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f) Maven home: D:\apache-maven-3.6.3\bin\.. Java version: 14.0.1, vendor: Oracle Corporation, runtime: C:\Java\jdk-14.0.1 Default locale: zh_CN, platform encoding: GBK OS name: "windows 10", version: "10.0", arch: "amd64", family: "windows"
解压后的子目录:
-
bin:存放可执行程序,主要是mvn.cmd
-
conf:maven工具本身的配置文件settings.xml
本地仓库默认是在: ${user.home}/.m2/repository,即C:/User/用户名/.m2/repository中。
通过conf文件可以修改本地仓库的地址
<localRepository>你的仓库的地址</localRepository>
Maven的核心概念
POM
POM 代表工程对象模型。它是使用 Maven 工作时的基本组建,是一个 xml 文件。它被放在工程根目录下,文件命名为 pom.xml。
POM 包含了关于工程和各种配置细节的信息,Maven 使用这些信息构建工程。
POM 也包含了目标和插件。当执行一个任务或者目标时,Maven 会查找当前目录下的 POM,从其中读取所需要的配置信息,然后执行目标。能够在 POM 中设置的一些配置如下:
- project dependencies
- plugins
- goals
- build profiles
- project version
- developers
- mailing list
在创建 POM 之前,我们首先确定工程组(groupId),及其名称(artifactId)和版本,在仓库中这些属性是工程的唯一标识。
POM 举例
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.companyname.project-group</groupId>
<artifactId>project</artifactId>
<version>1.0</version>
</project>
需要说明的是每个工程应该只有一个 POM 文件。
- 所有的 POM 文件需要 project 元素和三个必须的字段:groupId, artifactId,version。
- 在仓库中的工程标识为 groupId:artifactId:version
- POM.xml 的根元素是 project,它有三个主要的子节点:
| 节点 | 描述 |
|---|---|
| modelVersion | Maven模型的版本,对于Maven2和Maven3来说只能是4.0.0 |
| groupId | 这是工程组的标识。它在一个组织或者项目中通常是唯一的。例如,一个银行组织 com.company.bank 拥有所有的和银行相关的项目。 |
| artifactId | 这是工程的标识。它通常是工程的名称。例如,消费者银行。groupId 和 artifactId 一起定义了 artifact 在仓库中的位置。 |
| version | 这是工程的版本号。在 artifact 的仓库中,它用来区分不同的版本。例如: com.company.bank:consumer-banking:1.0 com.company.bank:consumer-banking:1.1. |
| packaging | 项目打包的类型,jar、war、ear等,默认是jar |
| dependencies和dependency | dependency来配置项目中的依赖,以坐标来定位。 |
| properties | 用来定义一些配置属性,<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>防止中文乱码。 |
| build | 与构建相关的配置,比如:编译插件的jdk版本,在properties中也可以设置。 |
约定的目录结构
Maven项目的目录和文件的位置都是规定的。
|项目名/
--|src
----|main # 放主程序java代码和配置文件
-------|java # 程序包和包中的java文件
-------|resources # java程序中使用的配置文件(图片/属性等)
----|test # 放测试程序用到的文件
-------|java # 测试程序包和包中的java文件
-------|resources # java程序中使用的配置文件(图片/属性等)
--|pom.xml # maven的核心文件,maven项目必须有
坐标
是一个唯一的字符串,用来表示资源的。Maven使用一组向量组成坐标来表示。
- groupId:组织名,通常是公司或者组织域名倒序+项目名称
- artifactId:模块名,通常是工程名。
- version:版本号
项目在仓库中的位置是由坐标决定:groupId、artifactId、version决定项目在仓库总的路径,artifactId和version决定jar包的名称。
依赖管理
管理项目中所使用的的jar文件
仓库管理
什么是 Maven 仓库?
在 Maven 的术语中,仓库是一个位置(place),例如目录,可以存储所有的工程 jar 文件、library jar 文件、插件或任何其他的工程指定的文件。
Maven 仓库有三种类型:
- 本地(local)
- 中央(central)
- 远程(remote)
本地仓库
Maven 本地仓库是机器上的一个文件夹。它在你第一次运行任何 maven 命令的时候创建。
Maven 本地仓库保存你的工程的所有依赖(library jar、plugin jar 等)。当你运行一次 Maven 构建,Maven 会自动下载所有依赖的 jar 文件到本地仓库中。它避免了每次构建时都引用存放在远程机器上的依赖文件。
Maven 本地仓库默认被创建在 %USER_HOME% 目录下。要修改默认位置,在 %M2_HOME%\conf 目录中的 Maven 的 settings.xml 文件中定义另一个路径。
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
http://maven.apache.org/xsd/settings-1.0.0.xsd">
<localRepository>C:/MyLocalRepository</localRepository>
</settings>
当你运行 Maven 命令,Maven 将下载依赖的文件到你指定的路径中。
中央仓库
Maven 中央仓库是由 Maven 社区提供的仓库,其中包含了大量常用的库。
中央仓库的关键概念:
- 这个仓库由 Maven 社区管理。
- 不需要配置。
- 需要通过网络才能访问。
要浏览中央仓库的内容,maven 社区提供了一个 URL:http://search.maven.org/#browse。使用这个仓库,开发人员可以搜索所有可以获取的代码库。
远程仓库
如果 Maven 在中央仓库中也找不到依赖的库文件,它会停止构建过程并输出错误信息到控制台。为避免这种情况,Maven 提供了远程仓库的概念,它是开发人员自己定制仓库,包含了所需要的代码库或者其他工程中用到的 jar 文件。
举例说明,使用下面的 POM.xml,Maven 将从远程仓库中下载该 pom.xml 中声明的所依赖的(在中央仓库中获取不到的)文件。
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.companyname.projectgroup</groupId>
<artifactId>project</artifactId>
<version>1.0</version>
<dependencies>
<dependency>
<groupId>com.companyname.common-lib</groupId>
<artifactId>common-lib</artifactId>
<version>1.0.0</version>
</dependency>
<dependencies>
<!--构建远程仓库-->
<repositories>
<repository>
<id>companyname.lib1</id>
<url>http://download.companyname.org/maven2/lib1</url>
</repository>
<repository>
<id>companyname.lib2</id>
<url>http://download.companyname.org/maven2/lib2</url>
</repository>
</repositories>
</project>
Maven 依赖搜索顺序
当我们执行 Maven 构建命令时,Maven 开始按照以下顺序查找依赖的库:
- 步骤 1 - 在本地仓库中搜索,如果找不到,执行步骤 2,如果找到了则执行其他操作。
- 步骤 2 - 在中央仓库中搜索,如果找不到,并且有一个或多个远程仓库已经设置,则执行步骤 4,如果找到了则下载到本地仓库中已被将来引用。
- 步骤 3 - 如果远程仓库没有被设置,Maven 将简单的停滞处理并抛出错误(无法找到依赖的文件)。
- 步骤 4 - 在一个或多个远程仓库中搜索依赖的文件,如果找到则下载到本地仓库已被将来引用,否则 Maven 将停止处理并抛出错误(无法找到依赖的文件)。
生命周期
maven工具构建项目的过程,就是生命周期。
当 Maven 开始构建工程,会按照所定义的阶段序列的顺序执行每个阶段注册的目标。Maven 有以下三个标准的生命周期:
- clean
- default(or build)
- site
clean生命周期
当 mvn clean 命令执行时,Maven 删除了构建目录。把之前项目编译的东西删除掉,为新的编译代码作准备。
如下图:编译之后会生成target目录。

执行mvn clean就会清除该目录。

Default (or Build) 生命周期
这是 Maven 的主要生命周期,被用于构建应用。包括下面的 23 个阶段。
| 生命周期阶段 | 描述 |
|---|---|
| validate | 检查工程配置是否正确,完成构建过程的所有必要信息是否能够获取到。 |
| initialize | 初始化构建状态,例如设置属性。 |
| generate-sources | 生成编译阶段需要包含的任何源码文件。 |
| process-sources | 处理源代码,例如,过滤任何值(filter any value)。 |
| generate-resources | 生成工程包中需要包含的资源文件。 |
| process-resources | 拷贝和处理资源文件到目的目录中,为打包阶段做准备。 |
| compile | 编译工程源码。 |
| process-classes | 处理编译生成的文件,例如 Java Class 字节码的加强和优化。 |
| generate-test-sources | 生成编译阶段需要包含的任何测试源代码。 |
| process-test-sources | 处理测试源代码,例如,过滤任何值(filter any values)。 |
| test-compile | 编译测试源代码到测试目的目录。 |
| process-test-classes | 处理测试代码文件编译后生成的文件。 |
| test | 使用适当的单元测试框架(例如JUnit)运行测试。 |
| prepare-package | 在真正打包之前,为准备打包执行任何必要的操作。 |
| package | 获取编译后的代码,并按照可发布的格式进行打包,例如 JAR、WAR 或者 EAR 文件。 |
| pre-integration-test | 在集成测试执行之前,执行所需的操作。例如,设置所需的环境变量。 |
| integration-test | 处理和部署必须的工程包到集成测试能够运行的环境中。 |
| post-integration-test | 在集成测试被执行后执行必要的操作。例如,清理环境。 |
| verify | 运行检查操作来验证工程包是有效的,并满足质量要求。 |
| install | 安装工程包到本地仓库中,该仓库可以作为本地其他工程的依赖。 |
| deploy | 拷贝最终的工程包到远程仓库中,以共享给其他开发人员和工程。 |
当一个阶段通过 Maven 命令调用时,例如 mvn compile,只有该阶段之前以及包括该阶段在内的所有阶段会被执行。
不同的 maven 目标将根据打包的类型(JAR / WAR),被绑定到不同的 Maven 生命周期阶段。
JAR是普通的java项目,WAR是java web项目。
Site 生命周期
Maven Site 插件一般用来创建新的报告文档、部署站点等。
插件和目标
maven工具构建项目时用到的插件。jar文件等。
命令行创建MAVEN项目
使用命令mvn archetype:generate创建maven项目
mvn archetype:generate # 交互式
输入完成之后,可能需要等待一会。之后会选择archetype,然后输入groupId、artifactId、version信息。
官方推荐groupId和package使用相同的路径
常用archetype
- maven-archetype-quickstart()
- maven-archetype-webapp(一个简单的Java Web应用程序)
- maven-archetype-simple
maven中测试文件的示例
package org.lowell;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
/**
* Unit test for simple App.
*/
public class AppTest
{
/**
* Rigorous Test :-)
*/
@Test
public void shouldAnswerWithTrue()
{
assertTrue( true );
}
}
通过idea使用maven
File--》settings--》Build,Excution,Deployment--》Build Tools--》Maven

Maven home directory:Maven的安装目录
User settings file:就是maven安装目录conf/settings.xml配置文件
Local repository:本机仓库的目录位置
maven项目创建时,会联网下载模板,比较大,时间较长,使用如下参数不用下载
File--》settings--》Build,Excution,Deployment--》Build Tools--》Maven--》Runner--》
VM Options:-DarchetypeCatalog=internal
Maven的外部依赖
现在,如你所知道的,Maven的依赖管理使用的是 Maven - 仓库的概念。但是如果在远程仓库和中央仓库中,依赖不能被满足,如何解决呢? Maven 使用外部依赖的概念来解决这个问题。
- 在 src 文件夹下添加 lib 文件夹
- 复制任何 jar 文件到 lib 文件夹下。我们使用的是 ldapjdk.jar ,它是为 LDAP 操作的一个帮助库
现在你有了自己的工程库(library),通常情况下它会包含一些任何仓库无法使用,并且 maven 也无法下载的 jar 文件。如果你的代码正在使用这个库,那么 Maven 的构建过程将会失败,因为在编译阶段它不能下载或者引用这个库。
为了处理这种情况,让我们用以下方式,将这个外部依赖添加到 maven pom.xml 中。
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.companyname.bank</groupId>
<artifactId>consumerBanking</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>consumerBanking</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ldapjdk</groupId>
<artifactId>ldapjdk</artifactId>
<scope>system</scope>
<version>1.0</version>
<systemPath>${basedir}\src\lib\ldapjdk.jar</systemPath>
</dependency>
</dependencies>
</project>
上例中, <dependencies> 的第二个 <dependency> 元素 , 阐明了外部依赖的关键概念。
- 外部依赖(library jar location)能够像其他依赖一样在 pom.xml 中配置。
- 指定 groupId 为 library 的名称。
- 指定 artifactId 为 library 的名称。
- 指定作用域(scope)为系统。
- 指定相对于工程位置的系统路径。
Maven的依赖范围
- maven的依赖范围包括: compile,provide,runtime,test,system。
- 编译依赖范围(compile),该范围就是默认依赖范围,此依赖范围对 于编译、测试、运行三种classpath都有效,举个简单的例子,假如项目中有spring-core的依赖,那么spring-core不管是在编译,测试,还是运行都会被用到,因此spring-core必须是编译范围(构件默认的是编译范围,所以依赖范围是编译范围的无须显示指定)
- 测试依赖范围(test),顾名思义就是针对于测试的,使用此依赖范围的依赖,只对测试classpath有效,在编译主代码和项目运行时,都将无法使用该依赖,最典型的例子就是 Junit, 构件在测试时才需要,所以它的依赖范围是测试,因此它的依赖范围需要显示指定为
test ,当然不显示指定依赖范围也不会报错,但是该依赖会被加入到编译和运行的classpath中,造成不必要的浪费 。 - 已提供依赖范围(provided),使用该依赖范围的maven依赖,只对编译和测试的classpath有效,对运行的classpath无效,典型的例子就是servlet-api, 编译和测试该项目的时候需要该依赖,但是在运行时,web容器已经提供的该依赖,所以运行时就不再需要此依赖,如果不显示指定该依赖范围,并且容器依赖的版本和maven依赖的版本不一致的话,可能会引起版本冲突,造成不良影响。
- 运行时依赖范围(runtime),使用该依赖范围的maven依赖,只对测试和运行的classpath有效,对编译的classpath无效,典型例子就是JDBC的驱动实现,项目主代码编译的时候只需要JDK提供的JDBC接口,只有在测试和运行的时候才需要实现上述接口的具体JDBC驱动。
- 系统依赖范围(system),该依赖与classpath的关系与 provided依赖范围完全一致,但是系统依赖范围必须通过配置systemPath元素来显示指定依赖文件的路径,此类依赖不是由maven仓库解析的,而且往往与本机系统绑定,可能造成构件的不可移植,因此谨慎使用,systemPath元素可以引用环境变量:
- 导入依赖范围(import),该依赖范围不会对三种classpath产生影响,该依赖范围只能与dependencyManagement元素配合使用,其功能为将目标pom文件中dependencyManagement的配置导入合并到当前pom的dependencyManagement中。
Maven - 工程文档
本教程将教你如何创建应用程序的文档。那么让我们开始吧,在项目目录下,执行以下 mvn 命令。
D:\myweb>mvn site

Maven - 快照
大型软件应用程序通常由多个模块组成,这是多个团队工作于同一应用程序的不同模块的常见场景。例如一个团队工作负责应用程序的前端应用用户接口工程(app-ui.jar:1.0)),同时他们使用数据服务工程(data-service.jar:1.0)。
现在负责数据服务的团队可能正在进行修正 bug 或者增强功能,并快速迭代,然后他们几乎每天都会 release 工程库文件到远程仓库中。
现在如果数据服务团队每天上传新的版本,那么就会有下面的问题:
- 每次数据服务团队发布了一版更新的代码时,都要告诉应用接口团队。
- 应用接口团队需要定期更新他们的 pom.xml 来得到更新的版本
为了解决这样的情况,快照概念发挥了作用.
什么是快照?
快照是一个特殊的版本,它表示当前开发的一个副本。与常规版本不同,Maven 为每一次构建从远程仓库中检出一份新的快照版本。
现在数据服务团队会将每次更新的代码的快照(例如 data-service:1.0-SNAPSHOT)发布到仓库中,来替换旧的快照 jar 文件。
快照 vs 版本
对于版本,Maven 一旦下载了指定的版本(例如 data-service:1.0),它将不会尝试从仓库里再次下载一个新的 1.0 版本。想要下载新的代码,数据服务版本需要被升级到 1.1。
对于快照,每次用户接口团队构建他们的项目时,Maven 将自动获取最新的快照(data-service:1.0-SNAPSHOT)。
应用用户接口 pom.xml
应用用户接口工程正在使用 1.0 版本的数据服务的快照
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>app-ui</groupId>
<artifactId>app-ui</artifactId>
<version>1.0</version>
<packaging>jar</packaging>
<name>health</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>data-service</groupId>
<artifactId>data-service</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
数据服务 pom.xml
数据服务工程为每个微小的变化 release 1.0 快照
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>data-service</groupId>
<artifactId>data-service</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>health</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
虽然,对于快照,Maven 每次自动获取最新的快照,但你可以在任何 maven 命令中使用 -U 参数强制 maven 下载最新的快照。
mvn clean package -U
让我们打开命令控制台,进入 C:\ > MVN > app-ui 目录并执行以下 mvn 命令。
C:\MVN\app-ui>mvn clean package -U
Maven将在下载数据服务的最新快照后,开始构建工程。
Maven全局变量
- 在properties中通过自定义标签声明变量(标签名就是变量名)
- 在pom.xml其他位置使用${标签名}使用变量的值。

资源插件
-
pom.xml中没有使用resources的时候,默认只将resources中的文件拷贝到target/classes中,不会将其他目录下的非java文件拷贝到target/classes的目录中。
-
有些需要把非java文件放到src/main/java目录下,当执行项目时,需要用到src/main/java目录下的文件,需要告诉maven在编译程序时将src/main/java下的非java文件也拷贝到target/classes目录中。此时就需要在pom.xml文件中使用
<build> <resources></resources> </build>示例
<build> <resources> <resource> <directory>src/main/java</directory> <!--文件所在目录--> <includes> <include>**/*.txt</include> </includes> <!--不启用过滤器,*.txt已经起到过滤作用--> <filtering>false</filtering> </resource> </resources> </build>
Maven多模块管理(继承)
maven父工程必须遵循以下两点要求
- packaging标签中的文本内容必须是pom
- 把src删除掉
maven多模块管理其实就是让他的子模块中的pom文件继承父模块的pom文件

浙公网安备 33010602011771号