Maven概述
-
Maven定义
- Maven是一个项目管理和整合,统一管理jar包的工具;
- Maven为开发者提供了一套完整的构建生命周期框架,可以让开发团队快速完成工程的基础构建配置,因为Maven使用了标准的目录结构和默认的生命周期;
- Maven能够帮助开发者完成构建、文档生成、报告、依赖、SCMs、发布、分发和邮件列表;
-
总结
- Maven简化了工程的构建过程,并对其标准化;
- 衔接了编译、发布、文档生成、团队合作和其他;
- Maven提高了重用性,负责大部分构建任务;
Maven历史
Maven最初是在Jakarta-Turbine项目中为了简化构建过程而设计的。项目中有几个子工程,每个工程包含稍有不同的 ANT 文件。JAR 文件使用 CVS 管理。
Apache 小组随后开发了Maven,能够同时构建多个工程、发布工程信息、部署工程、在几个工程中共享 JAR 文件,并且协助团队合作。-
Maven目的
- 主要是为开发这提供一个可复用、可维护、更易理解的工程综合模型
- 以及与这个模型交互的插件或者工具
Maven宗旨
始终贯彻一句话:约定优于配置
开发者不需要关心每一个配置细节。当创建Maven工程时,Maven会创建默认的工程结构,开发者只需要合理防止文件,在pom.xml中不需要再定义任何配置;
例如: Maven工程的默认结构(假定${basedir}表示工程目录)
配置项 | 默认值 |
---|---|
源代码 | ${basedir}/src/main/java |
配置文件 | ${basedir}/src/main/resources |
测试文件 | ${basedir}/src/test |
打包的jar包 | ${basedir}/target |
编译后的文件(字节码文件) | ${basedir}/target/classes |
Maven环境配置
- 系统要求
项目 | 要求 |
---|---|
JDK | Maven3.3要求JDK1.7或以上 Maven3.2要求JDK1.6或以上 Maven3.0/3.1要求JDK1.5或以上 |
内存 | 没有最低要求 |
磁盘 | Maven自身安装大约10MB空间,除此之外,都是用来存放本地仓库的jar包,预期至少500MB |
操作系统 | 没有最低要求 |
- 配置步骤
- 检查Java安装(JDK)
打开操作系统的命令行,然后输入命令:java -version - Java环境配置
操作系统 | 设置 |
---|---|
Windows | 环境变量 JAVA_HOME = Java的JDK安装目录,然后将JAVA_HOME添加到系统的环境变量Path后面 |
Linux | export JAVA_HOME=/usr/local/java-current,然后export PATH=PATH:JAVA_HOME/bin/ |
Mac | export JAVA_HOME=/Library/Java/Home |
- 下载Maven文件
从http://maven.apache.org/download.html下载Maven3.2.5 - 解压并配置Maven环境变量
解压文件,安装Maven3.2.5得到子目录apache-maven-3.2.5
操作系统 | 设置 |
---|---|
Windows | 使用系统属性设置环境变量 M2_HOME=C:\dictionary\apache-maven-3.2.5 M2=%M2_HOME%\bin MAVEN_OPTS=-Xms256m -Xmx512m,然后添加“;%M2%”到Path变量后面 |
Linux | 打开命令行设置环境变量 export M2_HOME=/usr/local/apache-maven/apache-maven-3.2.5 export M2=$M2_HOME/bin export MAVEN_OPTS=-Xms256m -Xmx512m 最后export PATH=M2:PATH |
Mac | 打开命令行设置环境变量 export M2_HOME=/usr/local/apache-maven/apache-maven-3.2.5 export M2=$M2_HOME/bin export MAVEN_OPTS=-Xms256m -Xmx512m 最后export PATH=M2:PATH |
- 验证Maven安装
打开操作系统的命令行,然后输入命令:mvn -version
Maven仓库
-
定义
Maven仓库:仓库是一个位置,可以存储所有工程的jar文件,library jar文件,插件或者其他工程指定的文件; -
类型
-
本地仓库
- Maven本地仓库是本地机器上的一个文件夹,在第一次运行任何maven命令的时候创建;
- 本地仓库在运行maven构建后,会自动下载并保存工程中需要的所有依赖、插件等到本地仓库中,避免每次构建都需要去远程仓库引用;
- 本地仓库的默认路径在User/用户名/.m2下,如果需要重新定义位置,可以在settings.xml文件中的localRepository标签中定义新的存放位置;
-
中央仓库
- 由Maven社区提供的仓库,包含了大量常用的库;
- 这个仓库由Maven社区管理;
- 不需要用户手动配置;
- 需要通过网络才能访问;
- 搜索Maven中央仓库的jar包依赖:http://search.maven.org/#browse
-
远程仓库
- 远程仓库是为了解决Maven在中央仓库找不到依赖的库文件而停止构建并报错这种情况;
- 远程仓库是开发人员你自己定制的仓库,包含了自己需要的代码或者其他项目需要的jar文件;
-
本地仓库
构建配置文件
- 定义
- 构建配置文件是一组配置的集合,用来设置或者覆盖Maven构建的默认配置,使用构建配置文件,可以为不同的环境定制构建过程,例如pro和dev环境。
- Profile在pom.xml中使用activeProfiles/profiles元素指定,而且可以用多种方式触发,Profile在构建时修改POM,并且为变量设置不同的目标环境,例如日志环境,kafka环境。
-
Profile
-
Profile类型
类型 使用 Pre Project 定义在POM文件的pom.xml中 Per User 定义在Maven设置xml文件中(%USER_HOME%/.m2/settings.xml) Global 定义在Maven全局配置xml文件中(%USER_HOME%/conf/settings.xml) Profile激活方法
- 显式使用命令控制台输入
- 通过maven设置
- 基于环境变量(用户/系统变量)
- 操作系统配置
- 现存/缺失文件
-
Maven POM
-
POM前言
定义:- POM代表工程对象模型,是使用Maven工作的基本组件,是一个xml文件,被放在工程根目录下,命名为pom.xml;
- POM包含了工程和各种配置细节的信息;
- POM也包含了目标和插件;
注意:
- 每个工程只有一个POM文件;
- 所有的POM文件需要根元素(project元素)和三个必须字段:groupId,artifactId,version;
- 在仓库中的工程标识为:groupId:artifactId:version;
-
POM用途
- pom.xml用来定义Maven工程结构和内容,是Project Object Model的简称;
- pom.xml是整个Maven系统的基础组件;
-
POM配置详解
-
POM配置组成
POM的模型版本:modelVersion标签,在Maven2和Maven3中,只支持4.0.0版本
基本配置
配置名称 描述 dependencies 项目引用插件所需要的额外的依赖 groupId 项目组ID artifactId 构件的标识符,它和groupId一起唯一标识一个构件 version 项目版本 packaging 项目打包方式,例如jar、war、ear、pom parent 引用的父项目 modules 引用的模块 properties 自定义的各种必要属性,在文件中可以使用${属性名}来引用 - build配置
配置名称 描述 build 构建项目需要的信息,主要标签:Resources(用于排除或者包含一些资源文件)和Plugins(设置构建的插件) reporting 使用报表插件产生的报表规范,当用户执行“mvn site”,这些报表就会运行 - 项目信息配置
配置名称 描述 issueManagement 给出defect tracking system及其访问URL ciManagement 给出Continuous Integration Management、其URL和notifier(集成过程中发生事件,以某种方式(如mail)通知开发人员) scm(software configuration management) connection、developerConnection、tag、url distributionManagement 构件的发布管理 prerequisites POM执行的前提条件,目前只支持对Maven版本的要求 mailingLists 开发人员或用户的邮件列表(name、subscribe、unsubscribe、post、archive、otherArchives) - 环境配置
配置名称 描述 name 项目的名称代号 description 项目说明 url 项目官网url inceptionYear 项目开发年份 licenses 可以包含多个license,以及子属性:name(license名称)、url(license可访问的url地址)、distribution(license发布方式)、comments(license说明) organization 包含组织的name,组织的官网url developers developer中包含id、name、email、url、organization、organizationUrl、roles、timezone、properties contributors contributor包含除了id之外的所有developer属性 POM元素继承
元素继承的原因:为了减少重复代码的编写,需要创建POM的父子结构,在父POM中申明一些供子POM继承的配置,实现“一处申明,多处使用”。
-
可继承的POM元素:
- groupId:项目组ID,项目坐标的核心元素
- version:项目版本,项目坐标的核心因素
- description:项目的描述信息
- organization:项目的组织信息
- inceptionYear:项目的创始年份
- url:项目的URL地址
- developers:项目的开发者信息
- contributors:项目的贡献者信息
- distributionManagement:项目的部署配置
- issueManagement:项目的缺陷跟踪系统信息
- ciManagement:项目的持续集成系统信息
- scm:项目的版本控制系统西溪
- malilingLists:项目的邮件列表信息
- properties:自定义的Maven属性
- dependencies:项目的依赖配置
- dependencyManagement:项目的依赖管理配置
- repositories:项目的仓库配置
- build:包括项目的源码目录配置、输出目录配置、插件配置、插件管理配置等
- reporting:包括项目的报告输出目录配置、报告插件配置等
-
聚合与继承的关系
- 区别
- 聚合模块知道那些被聚合的模块,但被聚合的模块不知道聚合模块的存在;
- 对于继承关系的父POM来说,不知道继承的字模块有哪些,但是字模块必须知道自己的父POM是什么。
- 共同点
- 聚合POM与继承关系中的父POM的packaging都是pom;
- 聚合模块与继承关系中的父模块除了POM之外都没有实际内容。
- 区别
-
依赖管理
依赖是使用Maven坐标来定位的,而Maven坐标主要由GAV(groupId, artifactId, version)构成。
在实际项目中,会存在pom文件,这时,如果不进行依赖管理,则会出现同一个依赖模块可能在不同的pom中都会出现,这就造成了重复依赖,在Maven中消除这种重复依赖的正确做法是:
1.在父模块中使用dependencyManagement配置依赖;
2.在子模块中使用dependencies添加依赖;
dependencyManagement实际上不会真正引入任何依赖,dependencies才会。但是,当父模块中配置了某个依赖之后,子模块只需使用简单groupId和artifactId就能自动继承相应的父模块依赖配置。-
依赖归类
依赖归类主要体现在依赖groupId相同的jar包的版本控制,例如依赖了spring相关jar包,spring-context、spring-core,要保证版本号相同,版本号不同,有时会出现兼容性问题。解决方法是在pom.xml中定义:<properties> <spring.version>2.5</spring.version> </properties> <dependencies> <dependency> <groupId>org.spring.framework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.spring.framework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> </dependencies>
-
依赖范围
作用域变量名 编译时有效 测试时有效 运行时有效 示例 compile √ √ √ smart-framework.jar(默认) test -- √ -- junit.jar runtime -- √ √ mysql-connector-java.jar provided √ √ -- servlet-api.jar system √ √ -- JDK的rt.jar -
分类器
分类器的命名模式为:artifactId-version-classifier.packaging
例如:<dependency> <groupId>org.testng</groupId> <artifactId>testng</artifactId> <version>5.7</version> <classifier>jdk15</classifier> </dependency>
分类器的用途:用来声明对test构件的依赖,比如我们在核心模块中声明了一些基础类,结果发现这个基础类对其他模块的测试类都有用,我们就可以把这个基础类打包成artifactId-version-test.jar,例如:
<dependency> <groupId>org.myorg.myapp</groupId> <artifactId>core</artifactId> <version>${project.version}</version> <classifier>test</classifier> </dependency>
-
生命周期
Maven强大的一个重要的原因是它有一个十分完善的生命周期模型(lifecycle),这个生命周期可以从两方面来理解:
- 顾名思义,运行Maven的每个步骤都由它来定义的,这种预定义的默认行为使得我们使用Maven变得简单,相比而言,Ant的每个步骤都要你手工去定义;
- 这个模型是一种标准,在不同的项目中,使用Maven的接口是一样的,这样就不用去仔细理解每个项目的构建了,一般情况下,mvn clean install 这样的命令是通用的。
Maven有三套、相互独立的生命周期
生命周期 | 描述 |
---|---|
clean | 在进行真正构建之前作一些清理工作 |
default(or build) | 构建的核心部分,编译、测试、打包、部署等等 |
site | 用来生成项目报告、站点、发布站点 |
注意:你可以仅仅调用clean来清理工作目录,也可以仅仅调用site来生成站点,也可以直接使用mvn clean install site完成这一套生命周期。
clean
当运行mvn clean时,clean生命周期一共包含了三个阶段:
阶段名称 | 描述 |
---|---|
pre-clean | 执行一些需要在clean之前完成的工作 |
clean | 移除所有上一次构建生成的文件 |
post-clean | 执行一些需要在clean之后立刻完成的工作 |
注意:mvn clean 中的clean就是上面的clean,在一个生命周期中,运行某个阶段的时候,它之前的所有阶段都会被运行,也就是说,mvn clean 等同于 mvn pre-clean clean ,如果我们运行 mvn post-clean ,那么 pre-clean,clean 都会被运行。
site
阶段名称 | 描述 |
---|---|
pre-site | 执行一些要在生成项目站点文档前完成的工作 |
site | 生成项目的站点文档 |
post-site | 执行一些需要在生成站点文档之后完成的工作,并且为部署做准备 |
site-deploy | 将生成的站点文档部署到特定的服务器上 |
经常会用到site阶段和site-deploy阶段,用以生成和发布Maven站点,完成文档和统计数据自动生成。
default(or build)
阶段名称 | 描述 |
---|---|
validate | 检查工程配置是否正确,完成构建过程的所有必要信息是否能够获取到 |
initialize | 初始化构建状态,例如设置属性 |
generate-sources | 生成编译阶段需要包含的任何源码文件 |
process-sources | 处理源代码,例如过滤任何值 |
generate-resources | 生成工程包中需要包含的资源文件 |
process-resources | 拷贝和处理资源文件到目的目录中,为打包阶段做准备 |
compile | 编译工程源码 |
process-classes | 处理编译生成的文件,例如Java Class 字节码的加强和优化 |
generate-test-sources | 生成编译阶段需要包含的任何测试源代码 |
process-test-sources | 处理测试源代码,例如过滤任何值 |
test-compile | 编译测试源代码到测试目录 |
process-test-classes | 处理测试代码文件编译后生成的文件 |
test | 使用适当的单元测试框架(例如JUnit)运行测试 |
prepare-package | 在真正打包之前,为准备打包执行任何必要的操作 |
package | 获取编译后的代码,并按照可发布的格式进行打包,例如JAR、WAR或者EAR文件 |
pre-integration-test | 在集成测试执行之前,执行所需的操作。例如设置所需的环境变量 |
integration-test | 处理和部署必须的工程包到集成测试能够运行的环境中 |
post-integration-test | 在集成测试被执行后执行必要的操作。例如清理环境 |
verify | 运行检查操作来验证工程包是有效的,并满足质量要求 |
install | 安装工程包到本地仓库中,该仓库可以作为本地其他工程的依赖 |
deploy | 拷贝最终的工程包到远程仓库中,以共享给其他开发人员和工程 |
注意:运行任何一个阶段,它前面的所有阶段都会被运行,这就是当我们运行mvn install时,代码会被编译、测试、打包的原因;而且,Maven的插件机制是完全依赖Maven的生命周期的。
Maven插件
-
插件和生命周期
使用mvn clean install构建Maven项目时:生命周期阶段 插件 clean clean插件 compile compile插件 process-test-resources resources插件 test-compile compiler插件 test surefire插件 package war/jar插件 install install插件 插件配置
有一个compiler常用的配置,因为compiler插件默认使用的是Java1.4的标准来编译源代码的,如果代码中用到了Java1.5的新特性,这样就会编译报错,所以要进行配置compiler插件支持Java 1.5;
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
Maven版本管理
-
定义
- 版本管理不是指的版本控制,版本指的是artifact的版本,而不是指源码的版本;
- 版本号我们可以通过修改pom中version之后,在构建一次就能改变,但是这样修改当我们同一个项目中有多个模块,这样改就会很麻烦;所以我们要了解如何自动化发布版本;
SNASHOT
SNAPSHOT是不稳定版本,还在开发中,每天都会提交新的代码,会频繁地发布新的版本;RELEASE
RELEASE是一段时间内的稳定版本,经过了多个SNAPSHOT版本;Maven版本规则
规则:<主版本>.<次版本>.<增量版本>;
主版本一般都是项目发生了大的架构变更;
此版本一般只是增加了一些功能,或者原有功能的修改;
增量版本则是修改的一些轻微的bug;-
相关插件
maven-release-plugin,这个插件会帮助我们升级pom版本,提交,打tag,然后再升级版本,再提交,等等,使用方法:<distributionManagement> <snapshotRepository> <id>nexus-snapshots</id> <name>Project SNAPSHOTS</name> <url>http://nexus.ops.7mxing.com/repository/maven-snapshots/</url> </snapshotRepository> <repository> <id>nexus-releases</id> <name>Project Release</name> <url>http://nexus.ops.7mxing.com/repository/maven-releases/</url> </repository> </distributionManagement> <!-- 发布插件 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-release-plugin</artifactId> <version>xxx</version> </plugin>