Maven是一个项目管理工具,提供了一套标准化的项目结构,所有IDE使用Maven构建的项目结构完全一样,所有IDE创建的Maven项目可以通用。
管理项目构建: maven提供一套对项目生命周期管理的标准,开发人员、和测试人员统一使用maven进行项目构建。项目生命周期管理:编译、测试、打包、部署、运行。
管理依赖(jar包): maven能够帮我们统一管理项目开发中需要的jar包;
管理插件: maven能够帮我们统一管理项目开发过程中需要的插件。
maven可以通过pom.xml中的配置,就能够获取到想要的jar包,但是这些jar是在哪里呢?就是我们从哪里获取到的这些jar包?答案就是仓库。仓库分为:本地仓库、第三方仓库(私服)和中央仓库。
本地仓库:计算机中一个文件夹,自己定义是哪个文件夹.Maven会将工程中依赖的构件(Jar包)从远程下载到本机的该目录下进行管理。maven默认的仓库是$user.home/.m2/repository目录。本地仓库的位置可以在$MAVEN_HOME/conf/setting.xml文件中修改。
在文件中找到localRepository,修改对应内容即可D:/maven/r2/myrepository
中央仓库:网上地址https://repo1.maven.org/maven2/这个公共仓库是由Maven自己维护,里面有大量的常用类库,并包含了世界上大部分流行的开源项目构件。工程依赖的jar包如果本地仓库没有,默认从中央仓库下载。由于maven的中央仓库在国外,所以下载速度比较慢,所以需要将中央仓库配置国内的镜像地址。
在配置文件中找到mirror标签,修改对应内容即可。
aliyunmaven
central
阿里云公共仓库
https://maven.aliyun.com/repository/public
第三方仓库(私服):第三方仓库,又称为内部中心仓库,也称为私服。私服:一般是由公司自己设立的,只为本公司内部共享使用。它既可以作为公司内部构件协作和存档,也可作为公用类库镜像缓存,减少在外部访问和下载的频率,公司单独开发的私有jar可放置到私服中。(使用私服为了减少对中央仓库的访问)
Maven坐标是资源的唯一标识,使用坐标来定义项目或引入项目中需要的依赖。
Maven坐标的主要组成:
groupId:定义当前Maven项目隶属组织名称(通常是域名反写,例如:com.baidu)
artifactId:定义当前Maven项目名称(通常是模块名称,例如 order-service、goods-service)
version:定义当前项目版本号
在Maven出现之前,项目构建的生命周期就已经存在,软件开发人员每天都在对项目进行清理,编译,测试及部署。虽然大家都在不停地做构建工作,但公司和公司间,项目和项目间,往往使用不同的方式做类似的工作。Maven的生命周期就是为了对所有的构建过程进行抽象和统一。Maven从大量项目和构建工具中学习和反思,然后总结了一套高度完美的,易扩展的生命周期。Maven的生命周期是抽象的,这意味着生命周期本身不做任何实际工作,在Maven的设计中,实际任务(如源代码编译)都交由插件来完成。
Maven拥有三套相互独立的生命周期,分别是clean,default和site。
clean生命周期的目的是清理项目,它包含三个阶段:
pre-clean 执行一些清理前需要完成的工作
clean 清理上一次构建生成的文件
post-clean 执行一些清理后需要完成的工作
default生命周期定义了真正构建项目需要执行的所有步骤,它是所有生命周期中最核心的部分。其中的重要阶段如下:
compile :编译项目的源码,一般来说编译的是src/main/java目录下的java文件至项目输出的主classpath目录中
test :使用单元测试框架运行测试,测试代码不会被打包或部署
package :接收编译好的代码,打包成可以发布的格式,如jar和war
install: 将包安装到本地仓库,供其他maven项目使用
deploy :将最终的包复制到远程仓库,供其他开发人员或maven项目使用
site生命周期的目的是建立和发布项目站点,maven能够基于pom文件所包含的项目信息,自动生成一个友好站点,方便团队交流和发布项目信息。该生命周期中最重要的阶段如下:
site :生成项目站点文档
Maven生命周期相关命令
mvn clean:调用clean生命周期的clean阶段,清理上一次构建项目生成的文件
mvn compile :编译src/main/java中的java代码
mvn test :编译并运行了test中内容
mvn package:将项目打包成可发布的文件,如jar或者war包;
mvn install :发布项目到本地仓库
Maven的核心包只有几兆大小,核心包中仅仅定义了抽象的生命周期。生命周期的各个阶段都是由插件完成的,它会在需要的时候下载并使用插件,例如我们在执行mvn compile命令时实际是在调用Maven的compile插件来编译。
maven在版本管理时候可以使用几个特殊的字符串 SNAPSHOT,LATEST ,RELEASE 。比如"1.0-SNAPSHOT"。各个部分的含义和处理逻辑如下说明:
SNAPSHOT 正在开发中的项目可以用一个特殊的标识,这种标识给版本加上一个"SNAPSHOT"的标记。
LATEST 指某个特定构件的最新发布,这个发布可能是一个发布版,也可能是一个snapshot版,具体看哪个时间最后。
RELEASE 指最后一个发布版。
maven项目之间的关系
依赖关系
标签把另一个项目的jar引入到当前项目
自动下载另一个项目所依赖的其他项目
继承关系
父项目是pom类型,子项目jar 或war,如果子项目还是其他项目的父项目,子项目也是pom 类型。
聚合关系
前提是继承关系,父项目会把子项目包含到父项目中。
子项目的类型必须是Maven Module 而不是maven project
新建聚合项目的子项目时,点击父项目右键新建Maven Module
聚合项目和继承项目区别
在语意上聚合项目父项目和子项目关系性较强;
在语意上单纯继承项目父项目和子项目关系性较弱。
什么是依赖?相信有过一定开发经验的人知道,每当我们需要使用某个框架时,比如 SpringMVC,那么我们需要导入相应的 jar 包,但是手动导入包的时候,往往会漏掉几个 jar 包,那么在使用该框架的时候系统就会报错。那么我们就说导入的包与未导入的包存在依赖关系。而使用 Maven,我们只需要在 pom.xml 文件中进行相应的配置,它就会帮助我们自动管理 jar 包之间的依赖关系。那么它是怎么管理的呢
我们以 Junit 为例,在 pom.xml 文件中进行详细而完整的配置。
junit
junit
3.8.1
...
...
...
...
...
dependencies:一个 pom.xml 文件中只能存在一个这样的标签。用来管理依赖的总标签。
dependency: 包含在 dependencies 标签中,可以有无数个,每一个表示一个依赖
groupId、artifactId 和 version:依赖的基本坐标,对于任何一个依赖来说,基本坐标是最重要的,Maven根 据坐标才能找到需要的依赖。
type:依赖的类型,对应于项目坐标定义的 packaging。大部分情况下,该元素不必声明,其默认值是 jar。
scope:依赖的范围,默认值是 compile。后面会进行详解。
optional:标记依赖是否可选。
exclusions:用来排除传递性依赖,后面会进行详细介绍。
「compile 范围依赖」
对主程序是否有效:有效
对测试程序是否有效:有效
是否参与打包:参与
是否参与部署:参与
典型例子:log4j
「test 范围依赖」
对主程序是否有效:无效
对测试程序是否有效:有效
是否参与打包:不参与
是否参与部署:不参与
典型例子:Junit
「provided 范围依赖」
对主程序是否有效:有效
对测试程序是否有效:有效
是否参与打包:不参与
是否参与部署:不参与
典型例子:servlet-api.jar,一般在发布到 服务器中,比如 tomcat,服务器会自带 servlet-api.jar 包,所以provided 范围依赖只在编译测试有效。
「runtime 范围依赖」:在测试、运行的时候依赖,在编译的时候不依赖。例如:JDBC 驱动,项目代码只需要 jdk 提供的 jdbc 接口,只有在执行测试和运行项目的时候才需要实现 jdbc 的功能。
依赖的排除
如果我们在当前工程中引入了一个依赖是 A,而 A 又依赖了 B,那么 Maven 会自动将 A 依赖的 B 引入当前工程,但是个别情况下 B 有可能是一个不稳定版,或对当前工程有不良影响。这时我们可以在引入 A 的时候将 B 排除。
exclusions:用来排除传递性依赖
依赖的冲突
在 maven 中存在两种冲突方式:一种是跨 pom 文件的冲突,一致是同一个 pom 文件中的冲突。
「跨 pom 文件,路径最短者优先」。比如我们在 Maven_first 中的 Junit 是4.9版本的,Maven_second 中的 Junit 是4.8版本的,由于 Maven_second 是 Maven_third 的直接依赖,明显相比于 Maven_first 路径要短,所以 Maven_third 的 Junit 版本与 Maven_second 保持一致
「同一个pom.xml 文件,先申明者优先」。
Clean Lifecycle:
pre-clean 执行一些需要在clean之前完成的工作
clean 移除所有上一次构建生成的文件
post-clean 执行一些需要在clean之后立刻完成的工作
Default Lifecycle:
validate
generate-sources
process-sources
generate-resources
process-resources 复制并处理资源文件,至目标目录,准备打包。
compile 编译项目的源代码。
process-classes
generate-test-sources
process-test-sources
generate-test-resources
process-test-resources 复制并处理资源文件,至目标测试目录。
test-compile 编译测试源代码。
process-test-classes
test 使用合适的单元测试框架运行测试。这些测试代码不会被打包或部署。
prepare-package
package 接受编译好的代码,打包成可发布的格式,如 JAR 。
pre-integration-test
integration-test
post-integration-test
verify
install 将包安装至本地仓库,以让其它项目依赖。
deploy 将最终的包复制到远程的仓库,以让其它开发人员与项目共享。
Site Lifecycle:
pre-site 执行一些需要在生成站点文档之前完成的工作
site 生成项目的站点文档
post-site 执行一些需要在生成站点文档之后完成的工作,并且为部署做准备
site-deploy 将生成的站点文档部署到特定的服务器上
Maven 插件原理
什么是 Maven 插件?上面我们讲了 Maven 的生命周期,我们知道 Maven 的核心是生命周期,生命周期指定了 Maven 命令执行的流程顺序。但是真正实现流程的工程是由插件来完成的。我们也可以说 Maven 是一个执行插件的框架,每一个任务实际上都是有插件来完成。进一步说每个任务对应了一个插件目标(goal),每个插件会有一个或者多个目标,例如 maven-compiler-plugin 的 compile 目标用来编译位于 src/main/java/ 目录下的主源码,testCompile 目标用来编译位于src/test/java/目录下的测试源码。
配置编译插件:
一般我们创建一个 Maven 工程,就算指定了 JDK 的版本,但是你执行 update project 操作,一般 Maven 工程会自动恢复到默认的 JDK 版本,有可能是1.4,有可能是1.5(和 Maven 版本有关)。
那么我们如何指定其 JDK 版本呢?在 pom.xml 中添加如下代码:
org.apache.maven.plugins
maven-compiler-plugin
1.7
1.7
UTF-8
聚合
需求场景:
在真实项目中,一个项目有表现层、业务层、持久层等。我们在用Maven 管理项目的时候,通常为创建多个 Maven 工程,也就是一个项目的多个模块。但是这样分成多个模块了,当我们进行项目打包发布的时候,那么要每一个模块都执行打包操作吗?这种重复的操作我们怎么才能避免呢?
解决办法:
创建一个聚合工程,将其他的各个模块都由这个聚合工程来管理,那么我们在进行项目发布的时候,只需要打包这个聚合工程就可以了。
第一步:创建聚合工程Maven Project(注意聚合工程的打包方式也必须为 pom,通常由 上面所讲的父工程来充当聚合工程)
第二步:创建子工程:业务层 选择 Maven Module。填写子工程模块名,打包方式选择 jar(子工程除了 web 层我们打包方式选择 war ,其余的都选择 jar)
第三步:创建子工程:表现层和持久层。创建步骤和前面一样,注意表现层打包方式我们要选择 war,因为要发布到 tomcat 容器运行。
第四步:在聚合工程中添加子工程的引用
xxx
xxxx
xxxxx
❝注意:这里虽然各个模块有依赖关系,但是可以不让依赖顺序添加,maven会自动识别依赖关系进行编译打包。
这里总的聚合工程随便哪个工程都可以,但是通常用 Parent 工程来完成。
Nexus 的全称是 Nexus Repository Manager(Nexus 仓库管理器),是 Sonatype 公司的一个产品。
Nexus 是一个强大的仓库管理器,极大地简化了内部仓库的维护和外部仓库的访问。
Nexus 分为开源版和专业版,其中开源版足以满足大部分 Maven 用户的需求。
Nexus 一般用来搭建位于组织或公司内部的 Maven 私服,代理所有的仓库(包括中央仓库),用户通过它就可以获取和管理所有所需的 Maven 构件。
Nexus 开源版具有以下优点:
占用内存小(28 M 左右)
具有基于 ExtJs 得操作界面,用户体验较好
使用基于 Restlet 的完全 REST API
支持代理仓库、宿主仓库和仓库组
基于文件系统,不需要依赖数据库
支持仓库管理
支持构件搜索
支持在界面上上传构件
这些优点使其日趋成为最流行的 Maven 仓库管理器。
4.0.0
项目组织唯一的标识符(com.xxx)
项目的唯一的标识符(项目名称)
版本号
项目组织唯一的标识符(com.xxx)
项目的唯一的标识符((项目名称))
打包类型
版本号
名称
描述
网址
工程的初始时间
1.7
3.0.1
2.1
4.11
5.1.21
UTF-8
javax.servlet
javax.servlet.api
3.0.1
provided
javax.servlet
javax.servlet.api
3.0.1
provided
证书列表