MAVEN学习笔记-基础

Posted by AceKei on October 2, 2018

转自 MAVEN

1. Maven生命周期

Maven的生命周期是对项目所有的构建过程进行抽象和统一。它包含了项目的清理、初始化、编译、测试、打包、部署和站点生成等构建步骤。Maven的生命周期本质是定义项目构建的各个步骤,它本身是抽象的,并不作任何的具体工作,而是将构建过程中的各个步骤任务交个相对应的插件来完成。这使得Maven的生命周期具有良好的扩展性,开发者可以自己编写插件实现代码绑定到构建的某个步骤。当然,在绝大部分场景下,开发者不必这样来做,因为Maven初始为项目构建的各个步骤绑定了默认的插件。

生命周期

Maven有三个相互独立的生命周期。它们分别是:Clean Default Site

生命周期 描述
Clean 用于清理项目
Default 用于构建项目
Site 用于生成项目站点

每个独立的生命周期都包含一些阶段(phase),这些阶段是一个有序的组合,后面的阶段依赖于前面的阶段。Maven主要的生命周期阶段在下表中已用加粗字体标出。

Clean生命周期
阶段 描述
pre-clean 在实际项目清理之前执行所需的过程
clean 删除上一个版本生成的所有文件
post-clean 执行完成项目清理所需的过程
Default生命周期
阶段 描述
validate 验证项目所有必要的信息都是可用的
initialize 初始化构建状态,例如设置属性或创建目录
generate-sources 生成包含在编译中的源代码
process-sources 处理源代码,过滤和替换一些变量的值
generate-resources 生成包含在包中的资源
process-resources 处理资源包,将其复制到目标目录
compile 编译项目的源代码
process-classes 从编译中对生成的文件进行后处理,如对Java类进行字节码增强
generate-test-sources 生成包含在编译中的测试源代码
process-test-sources 处理源代码,过滤和替换一些变量的值
generate-test-resources 生成包含在测试包中的资源
process-test-resources 处理资源包,将其复制到测试目标目录
test-compile 编译项目的测试源代码
process-test-classes 从编译中对生成的测试文件进行后处理,如对Java类进行字节码增强
test 执行单元测试,测试代码不会被打包部署
prepare-package 打包之前执行所需的任何操作
package 打包项目
pre-integration-test 集成测试前执行的操作,如设置环境等
integration-test 执行集成测试,如果需要,可将软件包部署到可运行集成测试的环境
post-integration-test 集成测试后执行的操作,如清理环境
verify 检查软件包是否符合标准
install 将项目输出构件安装到本地仓库
deploy 将项目输出构件部署到远程仓库
Site生命周期
阶段 描述
pre-site 在实际项目站点生成之前执行所需的过程
site 生成项目的站点文档
post-site 执行完成站点生成所需的进程,并准备站点部署
site-deploy 将生成的站点文档部署到指定的Web服务器
命令行命令

Maven执行项目构建的过程实质上是调用Maven生命周期阶段的过程。Maven主要的生命周期阶段并不多,其命令行命令几乎都是基于这些阶段的简单组合。而且Maven的大三生命周期是相互独立的,每个生命周期的阶段都有前后依赖的关系。任何一个简单的或组合的命令,只有当前面的阶段执行成功,后面的阶段才有机会得以继续执行。如果前面的某个阶段执行失败,后面的阶段就会被短路而导致无法继续执行下去。

1
$ mvn clean deploy
  • clean:调用Clean生命周期的clean和clean之前的所有阶段(即pre-clean和clean)
  • deploy:调用Default生命周期compile + test + package + install + deploy五个主要的阶段

因此,执行该命令最终达到的效果是:
清理项目 → 编译项目 → 单元测试 → 打包项目 → 将软件包安装到本地 → 将软件包发布到远程仓库

生命周期内置绑定的插件

Maven的生命周期是抽象的,它本身不做任何具体的工作,项目构建的过程实质是调用Maven生命周期阶段的过程,而Maven初始已经为生命周期的大部分阶段绑定了默认的插件,当外部调用Maven生命周期阶段的时候,绑定到这些阶段的插件就会来执行对应的具体工作。

Clean生命周期内置绑定的插件(详见Lifecycles Reference

阶段 插件
pre-clean  
clean maven-clean-plugin:2.5:clean
post-clean  

Default生命周期内置绑定的插件(详见Plugin Bindings for default Lifecycle Reference

阶段 插件
process-sources maven-resources-plugin:2.6:resources
compile maven-compiler-plugin:3.1:compile
process-test-sources maven-resources-plugin:2.6:testResources
test-compile maven-compiler-plugin:3.1:testCompile
test maven-surefire-plugin:2.12.4:test
package maven-jar-plugin:2.4:jar
maven-ejb-plugin:2.3:ejb
maven-plugin-plugin:3.2:addPluginArtifactMetadata
maven-war-plugin:2.2:war
maven-ear-plugin:2.8:ear
maven-rar-plugin:2.2:rar
install maven-install-plugin:2.4:install
deploy maven-deploy-plugin:2.7:deploy

Site生命周期内置绑定的插件(详见Lifecycles Reference

阶段 插件
pre-site  
site maven-site-plugin:3.3:site
post-site  
site-deploy maven-site-plugin:3.3:deploy

项目打包类型与生命周期内置绑定的插件

Maven项目的打包类型是由<packaging>xxoo</packaging>标签元素的值来决定的。可选值常见的有jar war pom,以及不太常用的maven-plugin ejb ear rar等。
Maven的Default生命周期为不同的打包类型内置绑定了不同的插件。而我们知道,项目构建过程的具体工作是由插件来完成的,因此不同的打包类型调用相同的Maven生命周期阶段,最终得以打出不同类型的软件包。

<packaging>pom</packaging>类型打包方式与生命周期内置绑定的插件

1
2
3
4
5
6
7
8
<phases>
    <install>
        org.apache.maven.plugins:maven-install-plugin:2.4:install
    </install>
    <deploy>
        org.apache.maven.plugins:maven-deploy-plugin:2.7:deploy
    </deploy>
</phases>

<packaging>jar</packaging>类型打包方式与生命周期内置绑定的插件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<phases>
    <process-resources>
        org.apache.maven.plugins:maven-resources-plugin:2.6:resources
    </process-resources>
    <compile>
        org.apache.maven.plugins:maven-compiler-plugin:3.1:compile
    </compile>
    <process-test-resources>
        org.apache.maven.plugins:maven-resources-plugin:2.6:testResources
    </process-test-resources>
    <test-compile>
        org.apache.maven.plugins:maven-compiler-plugin:3.1:testCompile
    </test-compile>
    <test>
        org.apache.maven.plugins:maven-surefire-plugin:2.12.4:test
    </test>
    <package>
        org.apache.maven.plugins:maven-jar-plugin:2.4:jar
    </package>
    <install>
        org.apache.maven.plugins:maven-install-plugin:2.4:install
    </install>
    <deploy>
        org.apache.maven.plugins:maven-deploy-plugin:2.7:deploy
    </deploy>
</phases>

<packaging>war</packaging>类型打包方式与生命周期内置绑定的插件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<phases>
    <process-resources>
        org.apache.maven.plugins:maven-resources-plugin:2.6:resources
    </process-resources>
    <compile>
        org.apache.maven.plugins:maven-compiler-plugin:3.1:compile
    </compile>
    <process-test-resources>
        org.apache.maven.plugins:maven-resources-plugin:2.6:testResources
    </process-test-resources>
    <test-compile>
        org.apache.maven.plugins:maven-compiler-plugin:3.1:testCompile
    </test-compile>
    <test>
        org.apache.maven.plugins:maven-surefire-plugin:2.12.4:test
    </test>
    <package>
        org.apache.maven.plugins:maven-war-plugin:2.2:war
    </package>
    <install>
        org.apache.maven.plugins:maven-install-plugin:2.4:install
    </install>
    <deploy>
        org.apache.maven.plugins:maven-deploy-plugin:2.7:deploy
    </deploy>
</phases>

2. Maven Super POM

所有maven模块(项目)的POM(Project Object Model,项目对象模型)都隐式的继承了Super POM。Super POM中定义了一组标准的配置变量。maven模块(项目)的POM会自动继承这些配置变量,你可以在maven模块(项目)的POM文件中直接使用它们,或者通过重新声明以覆盖它们。

倘若Maven安装的目录用{MAVEN_HOME}来表示,那么,Maven Super POM文件所在的路径为:{MAVEN_HOME}/lib/maven-model-builder-3.5.4.jar/org/apache/maven/model/pom-4.0.0.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
<?xml version="1.0" encoding="UTF-8"?>

<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License.
-->

<!-- START SNIPPET: superpom -->
<project>
  <modelVersion>4.0.0</modelVersion>

  <repositories>
    <repository>
      <id>central</id>
      <name>Central Repository</name>
      <url>https://repo.maven.apache.org/maven2</url>
      <layout>default</layout>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
    </repository>
  </repositories>

  <pluginRepositories>
    <pluginRepository>
      <id>central</id>
      <name>Central Repository</name>
      <url>https://repo.maven.apache.org/maven2</url>
      <layout>default</layout>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
      <releases>
        <updatePolicy>never</updatePolicy>
      </releases>
    </pluginRepository>
  </pluginRepositories>

  <build>
    <directory>${project.basedir}/target</directory>
    <outputDirectory>${project.build.directory}/classes</outputDirectory>
    <finalName>${project.artifactId}-${project.version}</finalName>
    <testOutputDirectory>${project.build.directory}/test-classes</testOutputDirectory>
    <sourceDirectory>${project.basedir}/src/main/java</sourceDirectory>
    <scriptSourceDirectory>${project.basedir}/src/main/scripts</scriptSourceDirectory>
    <testSourceDirectory>${project.basedir}/src/test/java</testSourceDirectory>
    <resources>
      <resource>
        <directory>${project.basedir}/src/main/resources</directory>
      </resource>
    </resources>
    <testResources>
      <testResource>
        <directory>${project.basedir}/src/test/resources</directory>
      </testResource>
    </testResources>
    <pluginManagement>
      <!-- NOTE: These plugins will be removed from future versions of the super POM -->
      <!-- They are kept for the moment as they are very unlikely to conflict with lifecycle mappings (MNG-4453) -->
      <plugins>
        <plugin>
          <artifactId>maven-antrun-plugin</artifactId>
          <version>1.3</version>
        </plugin>
        <plugin>
          <artifactId>maven-assembly-plugin</artifactId>
          <version>2.2-beta-5</version>
        </plugin>
        <plugin>
          <artifactId>maven-dependency-plugin</artifactId>
          <version>2.8</version>
        </plugin>
        <plugin>
          <artifactId>maven-release-plugin</artifactId>
          <version>2.5.3</version>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>

  <reporting>
    <outputDirectory>${project.build.directory}/site</outputDirectory>
  </reporting>

  <profiles>
    <!-- NOTE: The release profile will be removed from future versions of the super POM -->
    <profile>
      <id>release-profile</id>

      <activation>
        <property>
          <name>performRelease</name>
          <value>true</value>
        </property>
      </activation>

      <build>
        <plugins>
          <plugin>
            <inherited>true</inherited>
            <artifactId>maven-source-plugin</artifactId>
            <executions>
              <execution>
                <id>attach-sources</id>
                <goals>
                  <goal>jar-no-fork</goal>
                </goals>
              </execution>
            </executions>
          </plugin>
          <plugin>
            <inherited>true</inherited>
            <artifactId>maven-javadoc-plugin</artifactId>
            <executions>
              <execution>
                <id>attach-javadocs</id>
                <goals>
                  <goal>jar</goal>
                </goals>
              </execution>
            </executions>
          </plugin>
          <plugin>
            <inherited>true</inherited>
            <artifactId>maven-deploy-plugin</artifactId>
            <configuration>
              <updateReleaseInfo>true</updateReleaseInfo>
            </configuration>
          </plugin>
        </plugins>
      </build>
    </profile>
  </profiles>

</project>
<!-- END SNIPPET: superpom -->

Super POM 的作用

  1. 定义了一个ID为central的远程仓库(url即为这个仓库的地址),如果没有其它特殊的声明,maven模块(项目)所需要的构件(jar包等)都会到这个远程中央仓库中去下载;
  2. 定义了一个插件仓库,这个插件仓库和上面定义的远程仓库用的是同一个仓库,maven模块(项目)所需要的插件包都会到这个远程中央仓库中去下载;
  3. 定义了一组标准的配置变量,在maven模块(项目)的POM中可以通过${project.build.XX}来使用它们,如 ${project.build.directory};

    1
    2
    3
    4
    5
    6
    7
    
     <directory>${project.basedir}/target</directory>
     <outputDirectory>${project.build.directory}/classes</outputDirectory>
     <finalName>${project.artifactId}-${project.version}</finalName>
     <testOutputDirectory>${project.build.directory}/test-classes</testOutputDirectory>
     <sourceDirectory>${project.basedir}/src/main/java</sourceDirectory>
     <scriptSourceDirectory>${project.basedir}/src/main/scripts</scriptSourceDirectory>
     <testSourceDirectory>${project.basedir}/src/test/java</testSourceDirectory>
    

3. Maven发布构件到私服

Nexus3搭建的Maven私服为例子,用管理员账户登录系统平台,并在管理控制台的配置面板中创建一个用于发布项目构件的账户(注:在Maven中,所有的依赖、插件、项目构建的输出,都可以称作是构件)。

创建角色

在Nexus3管理控制台中,创建一个具有nx-component-uploadnx-repository-view-*-*-*两个权限的角色:

创建用户

在Nexus3管理控制台中,创建一个用作构件部署的账户,并将刚刚创建的角色分配给该用户:

settings.xml配置

在maven的用户或全局settings.xml配置文件,添加如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
<servers>
    <server>
        <id>nexus-maven-snapshot</id>
        <username>deployment</username>
        <password>deployment123</password>
    </server>
    <server>
        <id>nexus-maven-releases</id>
        <username>deployment</username>
        <password>deployment123</password>
    </server>
</servers>

<server>用于配置连接到远程服务器的账户名和账户密码。主要用于发布项目构件到Maven私服的时候,为本地连接远程私服服务器进行权限认证提供所需的用户名和密码。

pom.xml配置

在项目的pom.xml配置文件中,添加如下代码:

1
2
3
4
5
6
<distributionManagement>
    <repository>
        <id>nexus-maven-releases</id>
        <url>http://10.10.10.121:8081/repository/maven-releases/</url>
    </repository>
</distributionManagement>

注:如果项目是快照版本(项目pom.xml配置文件中version的值含有*-SNAPSHOT)则使用<snapshotRepository>标签替换<repository>标签。

  • <distributionManagement>用于配置项目构件发布到maven私服的哪个仓库中存储。
  • <id>的值必须与settings.xml配置文件中<server>子标签<id>的值匹配,否则在发布构件到maven私服时,会因查找不到账户和密码导致本地连接到远程私服服务器失败(maven构建的时候报401错误)。
  • <url>用于指定当前项目构件发布到maven私服时,具体上传存储到的那个仓库的地址。

部署构件

在命令行中执行命令:

1
$ mvn clean deploy

如果部署的构件是一个快照版本,由于存储快照版本的仓库是允许构件重新部署的,因此快照版本的构件在每次发布时都会自动带上一个时间戳标记,以作为区分和历史备份。如图所示:


4. Maven仓库

Maven仓库分为两种,一种是本地仓库,一种是远程仓库。
本地仓库是maven用来在本地机器上存储从远程仓库下载回来的构件的位置。
远程仓库包含了绝大多数流行的开源的java构件,项目依赖的构件一般都可以在这里下载。不同的远程仓库可能包含不同的java构件。

本地仓库和远程仓库的关系

远程仓库又分为:中央仓库(https://repo.maven.apache.org/maven2)、私服(如Nexus OSS)、其他第三方公共库(如阿里http://maven.aliyun.com/nexus/content/groups/public

大部分构件最初都是Maven从远程仓库下载回来存储到本地仓库的(也有一小部分是通过安装命令直接安装到本地仓库的),一旦Maven从远程仓库下载一个构件回来并存储到了本地仓库,只要你不手工删除该构件,同一个版本号的构件永远不需要去远程仓库下载第二次。因为Maven在构建项目查找依赖的构件时都首先会在本地仓库中去查找,如果在本地仓库查找不到才会去远程仓库中查找。一旦Maven在本地仓库查找到了依赖所需的构件,就不会再去远程仓库中去查找和下载了。

Maven本地仓库配置

在maven的用户或全局的settings.xml配置文件,如下:

1
2
3
4
5
<settings>
    
    <localRepository>D:/application/repo/maven</localRepository>
    
</settings>

<localRepository>用于指定本地仓库的位置。所有从远程仓库下载回来的构件都存储在这个位置。

Maven远程仓库配置

方式一,在maven的用户或全局的settings.xml配置文件中,找到<profiles>配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<profiles>
    <profile>
        ... ...
        <repositories>
            <repository>
                <id>nexus-maven-snapshots</id>
                <url>http://10.10.10.121:8081/repository/maven-snapshots/</url>
                <releases>
                    <enabled>true</enabled>
                </releases>
                <snapshots>
                    <enabled>true</enabled>
                </snapshots>
            </repository>
        </repositories>
        <pluginRepositories>
            <pluginRepository>
                <id>nexus-maven-snapshots</id>
                <url>http://10.10.10.121:8081/repository/maven-snapshots/</url>
                <releases>
                    <enabled>true</enabled>
                </releases>
                <snapshots>
                    <enabled>true</enabled>
                </snapshots>
            </pluginRepository>
        </pluginRepositories>
        ... ...
    </profile>
</profiles>

<repositories><pluginRepositories>在配置结构和作用上都相似,一个是用来配置远程仓库依赖类型的构件,另外一个是插件类型的构件。<id>必须是唯一的。<url>是这个仓库的地址。

方式二,在项目的pom.xml配置文件中,添加如下代码:

1
2
3
4
5
6
<repositories>
    <repository>
        <id>fanlychie-maven-repo</id>
        <url>https://raw.github.com/fanlychie/maven-repo/releases</url>
    </repository>
</repositories>

配置结构和在settings.xml中的结构一致。其区别在于,一个是在maven配置文件中配置,一个是在项目pom文件中配置。如果是针对某个或几个项目,可选择方式二来配置。

Maven仓库检索顺序

接下来做一个实验,在maven的用户或全局的settings.xml配置文件中,找到<profiles>配置:
并且在<repositories>标签中配置多个仓库,并且将仓库的顺序设置为如下(用仓库ID表示):
nexus-maven-snapshots → nexus-maven-releases → nexus-maven-3rd.party

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
<profiles>
    <profile>
        <id>jdk7-development</id>
        <activation>
            <jdk>1.7</jdk>
            <activeByDefault>true</activeByDefault>
        </activation>
        <properties>
            <maven.compiler.source>1.7</maven.compiler.source>
            <maven.compiler.target>1.7</maven.compiler.target>
            <maven.compiler.compilerVersion>1.7</maven.compiler.compilerVersion>
        </properties>
        <repositories>
            <repository>
                <id>nexus-maven-snapshots</id>
                <url>http://10.10.10.121:8081/repository/maven-snapshots/</url>
                <releases>
                    <enabled>true</enabled>
                </releases>
                <snapshots>
                    <enabled>true</enabled>
                </snapshots>
            </repository>
            <repository>
                <id>nexus-maven-releases</id>
                <url>http://10.10.10.121:8081/repository/maven-releases/</url>
                <releases>
                    <enabled>true</enabled>
                </releases>
                <snapshots>
                    <enabled>false</enabled>
                </snapshots>
            </repository>
            <repository>
                <id>nexus-maven-3rd.party</id>
                <url>http://10.10.10.121:8081/repository/3rd.party/</url>
                <releases>
                    <enabled>true</enabled>
                </releases>
                <snapshots>
                    <enabled>false</enabled>
                </snapshots>
            </repository>
        </repositories>
        <pluginRepositories>
            <pluginRepository>
                <id>nexus-maven-snapshots</id>
                <url>http://10.10.10.121:8081/repository/maven-snapshots/</url>
                <releases>
                    <enabled>true</enabled>
                </releases>
                <snapshots>
                    <enabled>true</enabled>
                </snapshots>
            </pluginRepository>
            <pluginRepository>
                <id>nexus-maven-releases</id>
                <url>http://10.10.10.121:8081/repository/maven-releases/</url>
                <releases>
                    <enabled>true</enabled>
                </releases>
                <snapshots>
                    <enabled>false</enabled>
                </snapshots>
            </pluginRepository>
            <pluginRepository>
                <id>nexus-maven-3rd.party</id>
                <url>http://10.10.10.121:8081/repository/3rd.party/</url>
                <releases>
                    <enabled>true</enabled>
                </releases>
                <snapshots>
                    <enabled>false</enabled>
                </snapshots>
            </pluginRepository>
        </pluginRepositories>
    </profile>
</profiles>

然后在项目的pom.xml配置文件中,添加如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<repositories>
    <repository>
        <id>fanlychie-maven-repo</id>
        <url>https://raw.github.com/fanlychie/maven-repo/releases</url>
    </repository>
</repositories>

<dependencies>
    <!-- 该构件托管在fanlychie-maven-repo仓库中 -->
    <dependency>
        <groupId>org.fanlychie</groupId>
        <artifactId>jexcel</artifactId>
        <version>2.2.2</version>
    </dependency>
</dependencies>

然后在命令行中执行命令:

1
$ mvn compile

命令执行时输出的日志信息:

可以看到,maven在下载依赖所需的构件时检索仓库的顺序依次为(仓库ID):nexus-maven-snapshots → nexus-maven-releases → nexus-maven-3rd.party → fanlychie-maven-repo → central
其本质的检索顺序是:本地仓库 → maven用户或全局配置文件settings.xml中的仓库 → 项目pom.xml文件中配置的仓库 → mavenSuper POM中配置的中央仓库
maven在下载依赖所需的构件时,如果这个构件在本地仓库找得到,就不会再去远程仓库中查找。如果这个构件在本地仓库中查找不到,就会按远程仓库配置时的顺序,去各个仓库里面一个一个的检索,只要这个构件在其中的任意一个仓库中查找到了,就不会再继续检索其他的仓库了。

这是第二次构建项目时输出的信息,可以看到,在第一次构建成功后,再次构建项目的时候就不会再去远程仓库下载构件了。


5. Maven镜像

如果一个仓库X可以提供仓库Y存储的所有构件,那么就可以称仓库X是仓库Y的一个镜像。由于地理位置等原因,国内网络连接Maven官方的中央仓库网速一般较慢或时常出现网络不稳定的状态,从而导致项目在构建所需的时间较长或失败。使用镜像的好处就是,它往往能提供比中央仓库更快的服务(通常选择地理位置上与自己较近且口碑较好的镜像), 从而提高下载速度, 最终达到提高项目构建效率的目的。

在maven的用户或全局的settings.xml配置文件中,找到在<mirrors>配置:

1
2
3
4
5
6
7
8
9
<mirrors>
    <mirror>
        <id>aliyun-maven-repo</id>
        <!-- 阿里云公共镜像 -->
        <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
        <!-- 匹配Maven中央仓库, 该ID在超POM中定义的 -->
        <mirrorOf>central</mirrorOf>
    </mirror>
</mirrors>

<mirror>用于配置一个镜像。<id>必须是唯一的。<url>是镜像的地址。<mirrorOf>用于匹配Maven仓库(<repository>)的ID。常见的匹配规则有:

通配符 描述
* 匹配所有的Maven仓库ID
repo1,repo2 只匹配ID为repo1或repo2的仓库
external:* 匹配除本地仓库之外的所有仓库
*,!repo1 匹配除ID为repo1之外的所有仓库

Maven在构建项目的时候,每当一个构件在本地仓库中查找不到时,它就会去远程中央仓库(central,Super POM中声明使用的远程仓库地址)中去下载。如果某个镜像的<mirrorOf>匹配到该仓库(如上面的aliyun-maven-repo镜像),则去这个仓库下载构件的请求就会被该镜像拦截掉,并将此次请求转发到该镜像配置的地址中去下载。本地所有访问远程仓库的请求都被转换成对镜像地址的请求,这就是镜像的作用和意义。