Maven学习笔记

Maven仓库的基本概念

当第⼀次运⾏Maven命令的时候, 你需要Internet链接, 因为它需要从⽹上下载⼀些⽂件。 那么它从 哪⾥下载呢? 它是从Maven默认的远程库下载的。 这个远程仓库有Maven的核⼼插件和可供下载的jar⽂件。

对于Maven来说, 仓库只分为两类: 本地仓库和远程仓库。

当Maven根据坐标寻找构件的时候,它⾸先会查看本地仓库,如果本地仓库存在,则直接使⽤; 如果 本地没有,Maven就会去远程仓库查找,发现需要的构件之后,下载到本地仓库再使⽤。 如果本地仓库和远程仓库都没有,Maven就会报错。

远程仓库分为三种: 中央仓库,私服, 其他公共库。

  • 中央仓库:默认配置下,Maven下载jar包的地⽅。

    由于原始的本地仓库是空的,maven必须知道⾄少⼀个可⽤的远程仓库,才能执⾏maven命令的时候 下载到需要的构件。中央仓库就是这样⼀个默认的远程仓库。 maven-model-builder-3.3.9.jar maven⾃动的 jar 中包含了⼀个 超级POM。定义了默认中央仓库的位 置。 中央仓库包含了2000多个开源项⽬,接收每天1亿次以上的访问

  • 私服:是另⼀种特殊的远程仓库,为了节省带宽和时间,应该在局域⽹内架设⼀个私有的仓库服务器, ⽤其代理所有外部的远程仓库。 内部的项⽬还能部署到私服上供其他项⽬使用

    私服是⼀种特殊的远程仓库,它是架设在局域⽹内的仓库服务, 私服代理⼴域⽹上的远程仓库,供局 域⽹内的maven⽤户使⽤。 当maven需要下载构件时, 它去私服当中找,如果私服没有, 则从外部远 程仓库下载,并缓存在私服上, 再为maven提供。 此外,⼀些⽆法从外部仓库下载的构件也能从本地上传到私服提供局域⽹中其他⼈使⽤

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <repositories>
    <repository>
    <snapshots>
    <enabled>true</enabled>
    </snapshots>
    <id>public</id>
    <name>Public Repositories</name>
    <url>http://192.168.0.96:8081/content/groups/public/</url>
    </repository>
    <repository>
    <id>getui-nexus</id> <url>http://mvn.gt.igexin.com/nexus/content/repositories/releases/</url>
    </repository>
    </repositories>

公司内部为何需要建立私服:

节省⾃⼰的外⽹带宽 加速maven构建 部署第三⽅控件 提⾼稳定性 降低中央仓库的负荷

常用的阿里云仓库配置,需要修改settings.xml文件

1
2
3
4
5
6
<mirror>
<id>nexus-aliyun</id>
<mirrorOf>central</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>

⼀般来说,在Maven项⽬⽬录下,没有诸如lib/这样⽤来存放依赖⽂件的⽬录。 当Maven在执⾏编译或 测试时,如果需要使⽤依赖⽂件,它总是基于坐标使⽤本地仓库的依赖⽂件。

每个⽤户在⾃⼰的⽤户⽬录下都有⼀个路径名为.m2/repository/的仓库⽬录。 有时候, 因为某些原因(⽐如c盘空间不⾜),需要修改本地仓库⽬录地址。

对于仓库路径的修改,可以通过maven 配置⽂件conf ⽬录下settings.xml来指定仓库路径。

1
2
3
4
<!-- 设置到指定⽬录中,路径的斜杆不要写反 -->
<settings>
<localRepository>D:/m2/repository</localRepository>
</settings>

Maven依赖的基本概念

根元素project下的dependencies可以包含多个 dependence元素,以声明多个依赖。每个依赖都应该包含以下元素:

  1. groupId, artifactId, version : 依赖的基本坐标, 对于任何⼀个依赖来说,基本坐标是最重要的, Maven根据坐标才能找到需要的依赖。

  2. Type: 依赖的类型,⼤部分情况下不需要声明。 默认值为jar

  3. Scope: 依赖范围(compile,test,provided,runtime,system)

compile:编译依赖范围

如果没有指定,就会默认使⽤该依赖范围。使⽤此依赖范围的Maven依赖,对于编译、测 试、运⾏三种classpath都有效。

test:测试依赖范围

使⽤此依赖范围的Maven依赖,只对于测试classpath有效,在编译主代码或者运⾏项⽬的使 ⽤时将⽆法使⽤此类依赖。典型的例⼦就是JUnit,它只有在编译测试代码及运⾏测试的时候才需要

provided:已提供依赖范围

使⽤此依赖范围的Maven依赖,对于编译和测试classpath有效,但在运⾏时⽆效。典型的例 ⼦是servlet-api,编译和测试项⽬的时候需要该依赖,但在运⾏项⽬的时候,由于容器已经提供,就不需要Maven重复地引⼊⼀遍(如:servlet-api)。

runtime:运行时依赖范围

使⽤此依赖范围的Maven依赖,对于测试和运⾏classpath有效,但在编译主代码时⽆效。典 型的例⼦是JDBC驱动实现,项⽬主代码的编译只需要JDK提供的JDBC接⼝,只有在执⾏测 试或者运⾏项⽬的时候才需要实现上述接⼝的具体JDBC驱动。

system:系统依赖范围

该依赖与三种classpath的关系,和provided依赖范围完全⼀致。但是,使⽤system范围依赖 时必须通过systemPath元素显式地指定依赖⽂件的路径。由于此类依赖不是通过Maven仓库 解析的,⽽且往往与本机系统绑定,可能造成构建的不可移植,因此应该谨慎使⽤。

  1. Optional:标记依赖是否可选

  2. Exclusions: ⽤来排除传递性依赖。

Maven依赖的依赖范围

⾸先需要知道,Maven在编译项⽬主代码的时候需要使⽤⼀套classpath。 ⽐如:编译项⽬代码的时候 需要⽤到spring-core, 该⽂件以依赖的⽅式被引⼊到classpath中。 其次, Maven在执⾏测试的时候会使 ⽤另外⼀套classpath。 如:junit。

最后在实际运⾏项⽬时,⼜会使⽤⼀套classpath, spring-core需要在该classpath中,⽽junit不需要。

那么依赖范围就是⽤来控制依赖与这三种classpath(编译classpath,测试classpath,运⾏时classpath)的 关系, Maven有以下⼏种依赖范围:(如上所述)

传递性依赖

传递依赖机制, 让我们在使⽤某个jar的时候就不⽤去考虑它依赖了什么。也不⽤担⼼引⼊多余的依 赖。 Maven会解析各个直接依赖的POM,将那些必要的间接依赖,以传递性依赖的形式引⼊到当前项⽬中。

注意:传递依赖有可能产生冲突

冲突场景”

A–>B—>C (2.0)

A–>E—>C (1.0)

如果A下同时存在两个不同version的C,冲突!!(选取同时适合A、B的版本)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<dependencies>
<dependency>
<groupId>A</groupId>
<artifactId>A</artifactId>
<version>xxx</version>
<exclusions>
<exclusion>
<groupId>C</groupId>
<artifactId>C</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>B</groupId>
<artifactId>B</artifactId>
</dependency>
</dependencies>
谢谢你的支持哦,继续加油.