一、Maven是什么?
Maven是一个软件(特别是Java软件)项目管理及自动构建工具,由Apache软件基金会所提供。基于项目对象模型(缩写:POM)概念,Maven利用一个中央信息片断能管理一个项目的构建、报告和文档等步骤。
二、为什么用Maven
1)依赖管理
maven 工程中不直接将 jar 包导入到工程中,而是通过在 pom.xml 文件中添加所需 jar 包的坐标,这样就很好的避免了 jar 直接引入进来,在需要用到 jar 包的时候,只要查找 pom.xml 文 件,再通过 pom.xml 文件中的坐标,到一个专门用于”存放 jar 包的仓库”(maven 仓库)中根据坐标从 而找到这些 jar 包,再把这些 jar 包拿去运行。
2)一键构建
什么是构建? 指的是项目从编译、测试、运行、打包、安装 ,部署整个过程都交给 maven 进行管理,这个 过程称为构建。
一键构建 指的是整个构建过程,使用 maven 一个命令可以轻松完成整个工作。
Maven 规范化构建流程:Maven将项目构建的过程进行标准化,每个阶段使用一个命令完成,大概如下:
校验-初始化-编译-测试-打包-集成测试-安装-部署
validate-initialize-compile-test-package-integrationTest-install-deploy
三、目录结构
1)普通Java项目目录结构
project
└─src 源码
├─main 主要
│ ├─java java源码
│ │ └─com
│ │ └─woniuxy
│ │ └─build 包名
│ └─resources 资源: 配置文件
└─test 测试相关
└─java
└─com
└─woniuxy
└─build
2)Javaweb项目结构
project
└─src
│ ├─main
│ │ ├─java ---存放项目的.java文件
│ │ ├─resource ---存放项目资源文件,如spring,hibernate配置文件
│ │ ├─webapp ---webapp目录是web工程的主目录
│ │ │ ├─WEB-INF
│ │ │ │ ├─web.xml
│ ├─test
│ │ ├─java ---存放所有测试.java文件,如JUnit测试类
│ │ ├─resource ---测试资源文件
│-target ---目标文件输出位置,如.class、.jar、.war文件
│-pro.xml ---maven项目核心配置文件
四、生命周期
默认生命周期的阶段 | default | 描述 | |
---|---|---|---|
1 | 验证 | validate | 确保当前配置和POM的内容是有效的。这包含对pom.xml文件树的验证。 |
2 | 初始化 | initialize | 在执行构建生命周期的主任务之前可以进行初始化。 |
3 | 生成源码 | generate-sources | 代码生成器可以开始生成在以后阶段中处理或编译的源代码。 |
4 | 处理源码 | process-sources | 提供解析、修改和转换源码。常规源码和生成的源码都可以在这里处理。 |
5 | 生成资源 | generate-resources | 可以生成非源码资源。通常包括元数据文件和配置文件。 |
6 | 处理资源 | process-resourers | 处理非源码资源。修改转换和重定位资源都能在这阶段发生。 |
7 | 编泽 | compile | 编译源码。编译过的类被放到目标目录树中。 |
8 | 处理类 | process-classes | 处理类文件转换和增强步骤。字节码交织器和常用工具常在这一一阶段操作。 |
9 | 生成测试源码 | generate-test-sources | mojo可以生成要操作的单元测试代码。 |
10 | 处理测试源码 | process-test-sources | 在编译前对测试源码执行任何必要的处理。在这一阶段,可以修改、转换或复制源代码。 |
11 | 生成测试资源 | generate-test-resources | 允许生成与测试相关的(非源码)资源。 |
12 | 处理测试资源 | process-test-resources | 可以处理、转换和重新定位与测试相关的资源。 |
13 | 测试编译 | test-compile | 编译单元测试的源码。 |
14 | 处理测试代码 | process-test-classes | 处理测试代码。 |
15 | 测试 | test | 运行编译过的单元测试并累计结果。 |
16 | 打包前准备 | prepare- package | 打包前准备 |
17 | 打包 | package | 将可执行的二进制文件打包到一个分布式归档文件中,如JAR或WAR |
18 | 前集成测试 | prepare-integration-test | 准备集成测试。这种情况下的集成测试是指在一个受到一定控制的模拟的真实部署环境中测试代码。这一一步能将归档文件部署到一个服务器上执行。 |
19 | 集成测试 | Integration-test | 执行真正的集成测试。 |
20 | 后集成测试 | postrintegration-test | 解除集成测试准备。这一一步涉及测试环境重置或重新初始化。为集成测试收尾。 |
21 | 检验 | vertify | 检验可部署归档的有效性和完整性。过了这个阶段,将安装该归档。 |
22 | 安装 | linstall | 将该归档添加到本地Maven目录。这一步让其他可能依赖该归档的模块可以使用它。 |
23 | 部署 | deploy | 将该B档添加到远程Maven目录。这一步让这个工件能为更多的人所用。 |
五、坐标
- groupId
定义当前 Maven 项目从属的实际项目。关于 groupId 的理解如下所示。
1)Maven 项目和实际项目不一定是一一对应的。比如 SpringFramework,它对应的 Maven 项目就有很多,如 spring-core、spring-context、spring-security 等。造成这样的原因是模块的概念,所以一个实际项目经常会被划分成很多模块。
2)groupId 不应该同开发项目的公司或组织对应。原因比较好理解,一个公司和一个组织会开发很多实际项目,如果用 groupId 对应公司和组织,那 artifactId 就只能是对应于每个实际项目了,而再往下的模块就没法描述了,而往往项目中的每个模块是以单独的形式形成构件,以便其他项目重复聚合使用。
3)groupId 的表述形式同 Java 包名的表述方式类似,通常与域名反向一一对应。 - artifactId
定义实际项目中的一个 Maven 项目(实际项目中的一个模块)。
推荐命名的方式为:实际项目名称-模块名称。
比如,org.springframework 是实际项目名称,而现在用的是其中的核心模块,它的 artifactId 为 spring-core。 - version
定义 Maven 当前所处的版本。如上的描述,用的是 4.2.7.RELEASE 版本。需要注意的是,Maven 中对版本号的定义是有一套规范的。具体规范请参考《版本管理》的介绍。 - packaging
定义 Maven 项目的打包方式。
打包方式通常与所生成的构件文件的扩展名对应,比如,.jar、.ear、.war、.pom 等。另外,打包方式是与工程构建的生命周期对应的。比如,jar 打包与 war 打包使用的命令是不相同的。最后需要注意的是,可以不指定 packaging,这时候 Maven 会自动默认成 jar。 - classifier
定义构件输出的附属构件。
附属构件同主构件是一一对应的,比如上面的 spring-core-4.2.7.RELEASE.jar 是 spring-core Maven spring-core 项目的主构。
Maven spring-core 项目除了可以生成上面的主构件外,也可以生成 spring-core-4.2.7.RELEASE-javadoc.java 和 spring-core-4.2.7.RELEASE-sources.jar 这样的附属构件。这时候,javadoc 和 sources 就是这两个附属构件的 classifier。这样就为主构件的每个附属构件也定义了一个唯一的坐标。
最后需要特别注意的是,不能直接定义一个 Maven 项目的 classifier,因为附属构件不是由 Maven 项目构建的时候直接默认生成的,而是由附加的其他插件生成的。
六、依赖
1)传递依赖
官方文档解释的传送门:http://ifeve.com/maven-dependency-mechanism/
当存在传递依赖的情况时,主工程对间接依赖的jar可以访问吗?
例如:A.jar依赖于B.jar,而B.jar依赖于C.jar,那么要怎么修改配置文件,才会让A.jar 也依赖 B.jar 呢?
这要看传递依赖的jar包引入时的依赖范围——只有依赖范围为compile时可以访问
即 要使A.jar 依赖于C.jar 当且仅当C.jar的范围是compile
如下演示HelloWrold2项目依赖 ——》HelloWrold项目依赖——》junit
此时HelloWrold这个项目是有junit.jar包的,而HelloWrold2是没有junit这个jar包的,如下所示:
需要在被依赖的项目HelloWorld的pom.xml上改写
改写之后,项目就出现了需要间接依赖的的jar包
2)依赖原则
依赖原则目的:防止jar包的冲突
为了避免造成依赖重复,需要选择一个依赖路径
- 路径最短优先原则
存在两个项目依赖同个类型但不同版本的jar包,这个时候会优先选择路径短的
项目配置情况:
HelloWrold2 依赖 HelloWrold
HelloWrold 依赖 Junit3.8 jar
HelloWrold 依赖 Junit4.0 jar
从图中看,显然junit3.8距离HelloWrold2更近点的
既然都拥有junit这个包,那么原本是 3.8 的 HelloWrold2 再依赖了HelloWrold后,会发生什么情况呢?
配置如下:
运行结果如图所示:此时HelloWrold保持原来的junit-3.8.jar不变
- 路径长度相同
路径长度相同的情况下,又可以分为是否有在同一个pom.xml两种情况
2.1 覆盖:
如果在同一pom.xml文件中有2个相同的依赖;后面声明的会覆盖前面的依赖
但这里要说严禁使用本情况,严禁在同一个pom中声明两个不同的依赖
2.2 优先:
如果是在不同pom.xml中有2个相同的依赖;则先声明的依赖,会覆盖后面生命的依赖
如下HelloWorld2依赖项目HelloWorld,和项目HelloWorld3
HelloWorld与HelloWorld3都有不同版本的commons-fileupload.jar
显然,先写在前面的HelloWorld3的jar包被采用了
七、仓库
在 Maven 的术语中,仓库是一个位置(place)。
Maven 仓库是项目中依赖的第三方库,这个库所在的位置叫做仓库。
在 Maven 中,任何一个依赖、插件或者项目构建的输出,都可以称之为构件。
Maven 仓库能帮助我们管理构件(主要是JAR),它就是放置所有JAR文件(WAR,ZIP,POM等等)的地方。
Maven 仓库有三种类型:
- 本地(local)
- 中央(central)
- 远程(remote)
1)本地仓库
Maven 的本地仓库,在安装 Maven 后并不会创建,它是在第一次执行 maven 命令的时候才被创建。
运行 Maven 的时候,Maven 所需要的任何构件都是直接从本地仓库获取的。如果本地仓库没有,它会首先尝试从远程仓库下载构件至本地仓库,然后再使用本地仓库的构件。
2)中央仓库
Maven 中央仓库是由 Maven 社区提供的仓库,其中包含了大量常用的库。
中央仓库包含了绝大多数流行的开源Java构件,以及源码、作者信息、SCM、信息、许可证信息等。一般来说,简单的Java项目依赖的构件都可以在这里下载到。
中央仓库的关键概念:
- 这个仓库由 Maven 社区管理。
- 不需要配置。
- 需要通过网络才能访问。
要浏览中央仓库的内容,maven 社区提供了一个 URL:http://search.maven.org/#browse。使用这个仓库,开发人员可以搜索所有可以获取的代码库。
3)远程仓库
如果 Maven 在中央仓库中也找不到依赖的文件,它会停止构建过程并输出错误信息到控制台。为避免这种情况,Maven 提供了远程仓库的概念,它是开发人员自己定制仓库,包含了所需要的代码库或者其他工程中用到的 jar 文件。
八、Maven 依赖搜索顺序
当我们执行 Maven 构建命令时,Maven 开始按照以下顺序查找依赖的库:
- 步骤 1 - 在本地仓库中搜索,如果找不到,执行步骤 2,如果找到了则执行其他操作。
- 步骤 2 -在中央仓库中搜索,如果找不到,并且有一个或多个远程仓库已经设置,则执行步骤 4,如果找到了则下载到本地仓库中以备将来引用。
- 步骤 3 -如果远程仓库没有被设置,Maven 将简单的停滞处理并抛出错误(无法找到依赖的文件)。
- 步骤 4 - 在一个或多个远程仓库中搜索依赖的文件,如果找到则下载到本地仓库以备将来引用,否则
Maven 将停止处理并抛出错误(无法找到依赖的文件)。
九、常用命令
- (1)mvn help:system:该命令打印出所有的java系统属性和环境变量。
- (2)mvn clean:清理输出目录默认target/。
- (3)mvn clean compline:编译项目主代码,默认编译至target/classes目录下。
- (4)mvn clean test:maven测试,但实际执行的命令有:clean:clean,resource:resources,compiler:compile,resources:testResources,compiler:testCompile,maven在执行test之前,会先自动执行项目主资源处理,主代码编译,测试资源处理,测试代码编译等工作,测试代码编译通过之后默认在target/test-calsses目录下生成二进制文件,紧接着surefile:test任务运行测试,并输出测试报告,显示一共运行了多少次测试,失败成功等等。
- (5)mvn celan package:maven打包,maven会在打包之前默认执行编译,测试等操作,打包成功之后默认输出在target/目录中。
- (6)mvn clean install:maven安装,让其他的项目直接引用这个项目。
- (7)echo %MAVEN_HOME%:查看maven安装路径。
- (8)mvn:检查是否安装了maven。
- (9)mvn dependency:list:查看当前项目中的已解析依赖
- (10)mvn dependency:tree:查看当前项目的依赖树
- (11)mvn dependency:analyse: 查看当前项目中使用未声明的依赖和已声明但未使用的依赖