Maven 学习总结 (一)
一、何为Maven
1、Maven是优秀的构建工具
maven的用途之一是用于构建,他是一个强大的构建工具,能够帮助我们自动化构建过程,从清理、编译、测试到生成报告,再到打包和部署。
他抽象了一个完整的构建生命周期模型,帮助我们标准化构建过程。
Maven作为一个构建工具,不仅能帮我们自动化构建,还能够抽象构建过程,提供构建任务实现;他跨平台,对外提供一致的操作接口,
这一切足以使它成为优秀的、流行的构建工具。
2、依赖管理工具和项目信息管理工具
Maven不仅是构建工具,还是一个依赖管理工具和项目信息管理工具。他提供了中央仓库,能帮我们自动下载构建。
他提供了一个优秀的解决方案,通过一个坐标系统准确地定位每一个构建(artifact),也就是通过一组坐标maven能够找到任何一类java类库。
我们可以借助它来有序地管理依赖,轻松解决那些复杂的依赖问题。
二、安装配置
1、具体安装步骤(略)
2、maven用户可以选择配置M2_HOME/conf/settings.xml或者~/.m2/settings.xml.
M2_HOME/conf/settings.xml 是全局范围的,整台机器上所有用户都会直接受到该配置的影响,
~/.m2/settings.xml. 是用户范围的,只有当前用户才会受到该配置的影响。
三、依赖管理
1、坐标和依赖
maven坐标为各种构件引入秩序,任何一个构建都必须明确定义自己的坐标,而一组坐标通过一些元素定义,他们是groupId、artifactId、version、packaging、classifier。
groupId:定义当前maven项目隶属于的实际项目。
artifactId:该元素定义实际项目中的一个maven项目(模块),推荐的做法是使用实际项目名称作为artifId的前缀。
version:该元素定义项目当前所处的版本。
packaging:该元素定义maven项目的打包方式,可选默认为jar。
classifier:该元素用来帮助定义构建输出的一些附属构件(nexus-indexer-2.0.0-javadoc.jar)不能直接定义项目的classifier,因为附属构件不是项目直接默认生成的,而是
由附加的插件帮助生成的。
scope:依赖范围,Maven在编译项目主代码的时候需要使用一套classpath,在编译和执行测试的时候会使用另外一套classpath,实际运行项目的时候,又会使用一套classpath。
依赖范围就是用来控制依赖与这三种classpath(编译classpath、测试classpath、运行classpath),maven有以下几种依赖范围:
- compile:编译依赖范围。默认使用该依赖范围。使用此依赖范围的maven依赖,对于编译、测试、运行三种classpath都有效。
- test:测试依赖范围。只对测试classpath有效。典型例子是JUnit,只有在编译测试代码及运行测试的时候才需要。
- provided:已提供依赖范围。对编译和测试classpath有效,在运行时无效。
- runtime:运行时依赖。对于测试和运行classpath有效,在编译代码时无效。
- system:系统依赖范围。和provided依赖范围完全一致。必须通过systemPath元素显示指定依赖文件的路径。
- import : 导入依赖范围,不对三种classpath产生实际影响。
2、依赖传递 :依赖范围不仅可以依赖与三种classpath的关系,还对传递性依赖范围。如图,最左边一行表示第一直接依赖范围,最上面一行表示第二直接依赖范围,
中间的交叉单元格则表示传递性依赖。
可以发现规律:第二直接依赖的范围是compile的时候,传递性依赖范围与第一直接依赖的范围一致
第二直接依赖范围是test的时候,依赖不得传递
第二直接依赖范围是provided的时候,只传递第一直接依赖范围也为provided的依赖
第二直接依赖范围是runtime的时候,传递依赖性范围与第一直接依赖范围一致。compile例外是runtime.
3、依赖调解: 项目A有这样的依赖关系:A-> B->C->X(1.0),A->D->X(2.0) 哪个版本的X会被maven解析使用呢?
Maven依赖调解的第一原则:路径最近者优先。 X(2.0)被解析。
A-> B->Y(1.0),A->C->X(2.0),依赖长度一样,都为2。谁会被解析使用呢?
第二原则:第一声明者优先。
在依赖路径长度相同的前提下,顺序最靠前的那个依赖优胜。在上例中如果B的依赖声明在C之前,那么Y(1.0)就会被解析使用。
4、可选依赖:<optional>true</optional>表示依赖为可选依赖,他们只对当前项目产生影响,当其他项目依赖当前项目是,这个依赖不会传递。
5、排除依赖:<exclusions><exclusion>......</exclusion></exclusions> 表示排除依赖。传递依赖会给项目隐式引入很多依赖,这极大简化了依赖管理
但是可能带来问题。使用排除依赖排除依赖,可以排除一个或者多个传递依赖。
Maven会自动解析所有项目的直接依赖和传递依赖,并根据规则正确判断每个依赖范围,对一些依赖冲突,能进行调节,以确保任何一个构件只有唯一的版本在依赖中存在,
在这些工作之后,最后得到的那些依赖被称为已解析依赖。 mvn dependency:list 可运行以上命令查看当前项目的已解析依赖。
6、优化依赖:maven会自动解析所有项目的直接依赖和传递依赖,并且根据规则正确判断每个依赖的范围,对于一些依赖冲突,也能进行调节,以确保任何一个构件只有
唯一的版本在依赖中存在。这些工作之后,最后得到的那些依赖被称为已解析依赖。
mvn dependency : list 查看当前项目已经解析依赖。
mvn dependency : tree 查看当前目录的依赖。
mvn dependency : analyze 可以帮助分析当前项目的依赖。该结果分两部分:首先是Used undeclared dependencies,意指项目中使用到的,但是没有显示声明的依赖。
还有一个重要的部分是Unused declared dependencies,意指项目中未使用的,但显示声明的依赖。
四、仓库
maven中任何一个依赖、插件或者项目构建的输出,都可以称为构件。任何一个构件都有唯一坐标,根据这个坐标可以定义其在仓库中的唯一存储路径,这是maven仓库
布局方式。maven仓库是基于简单文件系统存储的。
仓库分为本地仓库和远程仓库。maven根据坐标寻找构件的时候,先查看本地仓库,如果存在直接使用,如果不存在,或者要查看是否有更新版本,就去远程仓库查找。
私服是另一种特殊的远程仓库,为了节省带宽和时间,应该在局域网内架设一个私有仓库服务器。用其代理所有外部的远程仓库。
1、仓库配置
本地仓库:
中央仓库:
最原始的本地仓库是空的,maven至少知道一个可用的远程仓库,才能在执行maven命令的时候下载到需要的构建。中央仓库是一个默认的远程仓库。maven安装文件自带了
中央仓库的配置。打开jar文件$M2_HOME/lib/maven-model-builder-3.0.jar,访问路径org/apache/maven/model/pom-4.0.0.xml可以看到:
远程仓库:在settings.xml文件中
远程仓库:在pom文件中
<project>
...
<repositories>
<repository>
<id>jboss</id>
<name>JBoss Repository</name>
<url>http://repository.jboss.com/maven2/</url>
</repository>
</repositories>
远程仓库认证:有时我们需要提供认证信息才能访问一些远程仓库。配置认证信息和配置仓库信息不同,仓库信息可以配置在POM文件,但是认证信息必须配置在settings.xml中。
因为配置在settings.xml更为安全。
部署至远程仓库:maven除了能对项目进行编译、测试、打包之外,还能将项目生成的构建部署到仓库中。首先需要编辑项目的pom.xml文件,配置distributionManagement元素。
<project>
...
<distributionManagement>
<repository>
<id>jboss</id>
<name>JBoss Repository</name>
<url>http://repository.jboss.com/maven2/</url>
</repository>
<snapshotRepository>
<id>snapshot</id>
<name>Snapshot Repository</name>
<url>http://repository.snapshot.com/maven2/</url>
</snapshotRepository>
</repositories>
往远程仓库部署构件的时候,往往需要认证。认证方式就是需要在settings.xml中创建一个server元素,其id与仓库id匹配,并配置正确的认证消息。
配置正确后,在命令行运行命令:mvn clean deploy ,maven将醒目构建输出的构件部署到配置对应的远程仓库。如果项目当前版本是快照版本,则
部署到快照版仓库地址,否则部署到发布版本仓库地址。
从仓库解析依赖的机制:Maven是根据怎样的规则从仓库解析并使用依赖构件的呢? 当本地仓库没有依赖的构件的时候,Maven会自动从远程仓库下载;当依赖版本为快照
版本的时候maven会自动找到最新的快照。依赖解析机制可以概括如下:
1)当依赖的范围是system的时候,maven直接从本地文件系统解析构件
2)根据依赖坐标计算仓库路径后,尝试直接从本地仓库寻找构件,如果发现相应构件,则解析成功。
3)在本地仓库不存在相应构件的情况下,如果依赖的版本是显示的发布版本构件,则遍历所有的远程仓库,发现后,下载并解析使用。
4)如果依赖的版本是LATEST或者RELEASE,则更新策略读取所有远程仓库的元数据groupId/artifactId/version/maven-metadata.xml,将其与本地仓库的对应元数据合并后,得到
最新快照版本的值,然后基于该值检查本地仓库,或者从远程仓库下载。
5)如果是SNAPSHOT,则基于更新策略读取所有远程仓库的元数据groupId/artifactId/version/maven-metadata.xml,讲其与本地仓库的对应元数据合并后,得到最新
快照版本的值,然后基于这个真实的值检查本地仓库,或者远程仓库。
6)如果最后解析到的是时间戳格式的快照,则复制其时间戳格式的文件至非时间戳格式,如SNAPSHOT,并使用该非时间戳格式的构件。
当依赖的版本不明晰的时候,如RELEASE、LATEST和SNAPSHOT,maven就需要基于更新远程仓库的更新策略来检查更新。有一些配置与此有关:
首先,是<releases><enabled>和<snapshots><enabled>,只有仓库开启了对于发布版本的支持时,才能访问该仓库的发布版本构件信息,对于快照版本也会同理;
其次,要注意的是<releaes>和<snapshots>的子元素<updatePolicy>,该元素配置了检查跟新的频率,每日检查更新、永远检查更新、从不检查更新、自定义时间间隔更新等。
最后,用户还可从命令行加入参数-U,强制检查更新,使用参数后,Maven就会忽略<updatePlicy>的配置。
当maven检查完更新策略,并决定检查依赖更新的时候,就需要检查仓库元数据maven-metadata.xml。
RELEASE和LATEST版本,他们分别对应了仓库中存在的该构件的最新发布版本和最新版本(含快照),这两个最新是基于groupId/artifactId/version/maven-metadata.xml计算出来的。
该XML文件列出了仓库存在的该构建所有可能的版本,同时latest元素指向了这些版本中最新的那个版本,而release元素指向了这些版本中最新的发布版本。
maven通过合并多个远程仓库及本地仓库的元数据,就能计算出基于所有仓库的latest和release分别是什么,然后再解析具体的构件。
依赖声明中使用LATEST和RELEASE是不推荐的做法,因为maven随时都可能解析到不同的构件,可能今天latest是1.3.6,明天就成为1.4.0-SNAPSHOT了,
且maven不会明确告诉用户这样的变化。当这种变化造成构建失败的时候,发现问题会变得比较困难。release因为对应的是最新的发布版本构件,还相对可靠,
latest就非常不可靠了,为此maven3不再支持在插件配置中使用latest和release 。如果不设置产检版本,其效果就和release一样,maven只会解析最新的发布版本构件,
不过即使这样,还存在潜在的问题。
镜像:如果仓库X可以提供仓库Y存储的所有内容,那么就可以认为X是Y的一个镜像。镜像配置:
该例中,<mirrorOf>的值为central,表示该配置为中央仓库的镜像,任何对于中央仓库的请求都会转至该镜像。镜像最为常见的用法是结合私服,由于私服
可以代理所有的仓库。对于用户来说,使用一个私服地址就等于使用了所有需要的外部仓库,这可以讲配置集中到私服,从而简化maven本身的配置。
Maven 学习总结 (一)的更多相关文章
- Maven学习-目录结构
在前一篇文章中,我们介绍了什么是Maven,以及如何用Maven来构建我们的项目.不了解Maven的童鞋,可以看这里Maven学习-入门.在这篇文章中,我们将学习Maven的项目的目录结构相关的内容. ...
- Maven学习笔记-03-Eclipse下maven项目在Tomcat7和Jetty6中部署调试
现在最新的Eclipse Luna Release 已经内置了Maven插件,这让我们的工作简洁了不少,只要把项目直接导入就可以,不用考虑插件什么的问题,但是导入之后的项目既可以部署在Tomcat也可 ...
- maven学习之二M2_HOME简介
在<maven学习之一>中介绍了M2_HOME指向了maven的安装目录,如下图: weiwan..................
- Maven学习:Eclipse使用maven构建web项目(转)
Maven学习:Eclipse使用maven构建web项目(转) 8.更改class路径:右键项目,Java Build Path -> Source 下面应该有4个文件夹.src/main/j ...
- Maven学习系列二(1-5)
Maven学习系列二(1-5) 本文转自 QuantSeven 博客,讲解精炼易懂,适合入门,链接及截图如下 http://www.cnblogs.com/quanyongan/category/47 ...
- Maven学习总结(1-10)
Maven学习总结(1-10) 本文转自 孤傲苍狼 博客,讲解精炼易懂,适合入门,链接及截图如下 http://www.cnblogs.com/xdp-gacl/tag/Maven%E5%AD%A6% ...
- MAVEN学习(初级)
1. 项目管理利器 MAVEN 学习,参考慕课网 :http://www.imooc.com/search/?words=maven 2. 下载MEAVN 地址:http://maven.apache ...
- maven学习3,如何创建一个web项目
Maven学习 (三) 使用m2eclipse创建web项目 1.首先确认你的eclipse已经安装好m2eclipse的环境,可以参照上两篇Maven学习内容 2.新建一个maven的项目 ...
- Maven学习(六)-- Maven与Eclipse整合
由于我使用的是IDEA所以就不摘录了,感兴趣的移步 Maven学习总结(六)--Maven与Eclipse整合 Maven学习总结(七)--eclipse中使用Maven创建Web项目
- TODO maven学习笔记
maven是什么? 我的体会 我理解得maven就是一个构建工具,可以做一些项目得整合操作,我们把一些常见得操作,封装在maven里面,并给它命名成 clean,test,compile,这些步骤都是 ...
随机推荐
- [spring boot] Table 'yhm.hibernate_sequence' doesn't exist
在使用该注解时:@GeneratedValue要注意的几点: @GeneratedValue注解的strategy属性提供四种值: -AUTO主键由程序控制, 是默认选项 ,不设置就是这个 -IDEN ...
- SQLServer删除数据列
删除数据列 开发或者生产过程中多建.错误或者重复的数据列需要进行删除操作. 使用SSMS数据库管理工具删除数据列 方式一 1.打开数据库->选择数据表->展开数据表->展开数据列-& ...
- 一篇文章教你如何用 Python 记录日志
前言: 这篇文章是我copy别人的,但是个人认为讲的真的很细致,有原理有实例,不仅仅只教你如何使用日志更会叫你知道日志的原理,真的非常棒,虽然文章很长,也许你不会认认真真读完, 但是当你遇到问题时这篇 ...
- 索引-mysql
什么是索引 索引的四大作用 (参考百度百科:百度百科-索引) 索引的优缺点 索引分类 什么地方需要建索引 索引优化 什么是索引? 宏观来说,索引是一种检索工具,目录也是一种检索工具,但是两者是有区是别 ...
- 我的第一个python web开发框架(26)——定制ORM(二)
弄完底层数据库操作模块后,接下来要做的是ORM的正式设计.在开始之前,我们需要思考一下怎么来设计一个ORM呢?这个类它能帮助我们处理什么样的问题?需要有哪些功能模块?怎么做到针对不同的数据库与表单进行 ...
- 日志学习系列(三)——NLog基础知识
前边我们解释了log4net的学习,我们再介绍一下NLog 一.什么是NLog NLog是一个基于.NET平台编写的类库,我们可以使用NLog在应用程序中添加极为完善的跟踪调试代码.NLog是一个简单 ...
- ASP.NET MVC5学习系列——身份验证、授权
一.什么是身份验证和授权 人们有时对用户身份验证和用户授权之间的区别感到疑惑.用户身份验证是指通过某种形式的登录机制(包括用户名/密码.OpenID.OAuth等说明身份的项)来核实用户的身份.授权验 ...
- 返回数组中指定的一列,将键值作为元素键名array_column
array_column() 函数 从记录集中取出 last_name 列: <?php // 表示由数据库返回的可能记录集的数组 $a = array( array( 'id' => 5 ...
- Java Scanner 类
下面是创建 Scanner 对象的基本语法: Scanner s = new Scanner(System.in); Scanner -是java类库的一个基础类,一个可以使用正则表达式来解析基本类型 ...
- vue-使用keep-alive优化网页性能
export default{ name: 'Home', data () { return { iconList: [], recommendList: [], swiperList: [], we ...