# maven 中 geo tools 的引入 - maven 的 repository 与 mirror
# maven 中 geo tools 的引入 - maven 的 repository 与 mirror
# 一,问题描述
起因是这样的,我想要引入 GeoTools 包,却发现即使按照官方 quick start 来操作,也没有引入成功,始终是找不到 jar 包,百思不得其解。
按照官网和谷歌百度搜索的结果看
要使用 GeoTools,首先引入需要的 GeoTools 的模块。GeoTools 有很多模块,如 shapefile,csv 等。
这个是我要引入的 geojson 模块
<dependency> | |
<groupId>org.geotools</groupId> | |
<artifactId>gt-geojson</artifactId> | |
<version>19.0</version> | |
</dependency> |
然后添加 geo tools 官方的仓库
<repository> | |
<id>osgeo</id> | |
<name>OSGeo Release Repository</name> | |
<url>https://repo.osgeo.org/repository/release/</url> | |
<snapshots><enabled>false</enabled></snapshots> | |
<releases><enabled>true</enabled></releases> | |
</repository> | |
<repository> | |
<id>osgeo-snapshot</id> | |
<name>OSGeo Snapshot Repository</name> | |
<url>https://repo.osgeo.org/repository/snapshot/</url> | |
<snapshots><enabled>true</enabled></snapshots> | |
<releases><enabled>false</enabled></releases> | |
</repository> |
但就是找不到 jar 包
dependencies 也是报错
后来尝试将仓库以镜像的方式写入到 settings.xml 之中,结果发现可行了。(当然后续发现这种方法是错误的解决方案,正确的做法在后面)
# 二,原理说明
出错原因: 没有理解清楚 maven 的 repository 与 mirror 的关系,错误地将阿里云镜像的 mirrorOf 参数值设置为 *(星号,通配符,表示匹配全部仓库)(正确的参数值为 central)
为了让各位更好地理解这个问题,有必要占用一些篇幅介绍一下 maven 的基本信息和相关概念
# 2.1 maven 的主要功能
以下描述摘自维基百科
Maven 是一个主要用于 Java 项目的构建自动化工具。Maven 还可以用来构建和管理使用 c#、Ruby、Scala 和其他语言编写的项目。Maven 项目由 Apache 软件基金会托管,它以前是 Jakarta 项目的一部分。
Maven 解决了构建软件的两个方面:如何构建软件及其依赖关系。
maven 的主要功能有两个:一个是解决项目的构建:包括编译(build)、测试(test)、** 打包(package)和部署(deploy)** 等,maven 使用生命周期的概念描述这一过程,并通过插件实现和控制项目构建各个阶段的执行。
下图为完整的 maven 生命周期
maven 的另一个功能就是解决项目之间的依赖关系并从仓库 (repository) 自动下载需要的 jar 包。maven 使用项目对象模型 (Project Object Model,POM) 实现对项目的抽象和管理。
项目对象模型 (POM) 提供了单个项目的所有配置。一般配置包括项目的名称(name)、所有者(owner)及其对其他项目的依赖关系(dependencies)。还可以配置构建过程的各个阶段,这些阶段以插件(plugins)的形式实现。
默认情况下,所有的 POM 都继承自超级 POM。超级 POM 提供默认配置,比如默认源目录、默认插件等等。
maven 将约定大于配置作为其设计理念,约定一一些默认的配置,如项目的默认结构,对某个项目坐标,依赖和插件的规定的配置方法 (IDE 通常会帮助检查配置项的正确性) 等。
下图表示默认的 maven 项目 目录
# 2.2 仓库
所有的 maven 项目都存储在服务器上,改服务器被抽象为仓库 (repository),当用户需要某些 jar 包时就可以从仓库中下载。
maven 通过超级 POM 机制配置了默认的仓库。由于所有的 POM 都隐式地继承自超级 POM,超级仓库中配置了中央仓库,因此所有的项目默认配置了中央仓库。
对于 Maven3,超级 POM 在文件 % MAVEN_HOME%/lib/maven-model-builder-x.x.x.jar 中的
org/apache/maven/model/pom-4.0.0.xml 路径下、对于 Maven2,超级 POM 在文件 % MAVEN_HOME%/lib/maven-x.x.x-uber.jar 中的
org/apache/maven/project/pom-4.0.0.xml 目录下。
默认配置的部分内容如下:
<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> |
我们可以自己添加仓库,如我添加了提供 GeoTools 相关包的仓库,id 为 osgeo
,url 地址为 https://repo.osgeo.org/repository/release/
。
在项目的 pom.xml 中加入仓库配置:
<repository> | |
<id>osgeo</id> | |
<name>OSGeo Release Repository</name> | |
<url>https://repo.osgeo.org/repository/release/</url> | |
<snapshots><enabled>false</enabled></snapshots> | |
<releases><enabled>true</enabled></releases> | |
</repository> |
# 2.3 镜像
由于 maven 的中央仓库在国外,国内访问速度较慢,一般我们采用配置镜像(mirror)的方式从国内的镜像服务器中下载资源。
maven 根据 setting.xml 文件中配置的镜像拦截发往原仓库的请求,并将其转发到镜像仓库。
即:当一个镜像的 mirrodOf 参数与某个仓库的 id 参数相匹配,就向该镜像请求资源,否则向原仓库请求资源。
阿里云镜像是常用的 maven 镜像之一,其镜像了中央仓库的所有资源。
setting.xml 文件中阿里云镜像的配置如下:
<!-- 阿里云镜像 --> | |
<mirror> | |
<id>nexus-aliyun</id> | |
<mirrorOf>central</mirrorOf> | |
<name>Nexus aliyun</name> | |
<url>http://maven.aliyun.com/nexus/content/groups/public</url> | |
</mirror> |
在 setting.xml 文件中,我们设置阿里云镜像的 mirrorOf
属性为 central
,以此去匹配 id
属性为 central
的中央仓库。这样所有对中央仓库发起的请求,都会被转发给阿里云镜像,大大提高了资源的下载速度。
# 2.4 仓库与镜像的关系
当我们配置了多个仓库和多个镜像时,maven 执行的策略为:
1,maven 根据镜像配置文件(setting.xml)自上至下地依次查看所有的镜像,对每一个仓库依次进行匹配,并使用第一个匹配上的镜像。被镜像匹配的仓库,仓库的 url 被替换为镜像的 url,没有匹配的仓库,url 不变。
2,查询各仓库是否包请求的资源(项目),如都没有,则报错(如未找到),否则从第一个匹配上的仓库拉取资源。
# 三,解决方案与小技巧
1,不是所有的 jar 包都被包含在 maven 中央仓库中,如果中央仓库没有该资源,就需要配置第三方仓库(也可以理解为别人的公开私服)。maven 中央仓库不包含 GeoTools 的相关资源,因此需要单独配置 OSGeo Release Repository 仓库。
2,阿里镜像和清华镜像只提供对中央仓库的资源镜像,其 mirrorOf 属性的值只能设置为 central,不要设置为 * 。如果设置为 *,则所有仓库的 url 都会被替换,对于本文的情况,就是本来应当发往 OSGeo Release Repository 仓库的请求被发往阿里云镜像,而阿里云镜像不包含 GeoTools 的资源,自然是找不到了。正确的做法是每个镜像的 mirrorOf 属性应与该镜像对应的仓库的 id 属性保持一致。
3,还有一种骚操作(错误操作),就是在 setting.xml 将仓库作为镜像配置进去。由于 maven 的镜像机制,仓库的 url 会被替换为第一个匹配上的镜像,那么在阿里云镜像之前添加一个(伪)仓库镜像,也可以解决问题。但是这个方法肯定是错误用法(但是很骚)。
# 错误配置
setting.xml
<!-- 阿里云镜像 --> | |
<mirror> | |
<id>nexus-aliyun</id> | |
<mirrorOf>*</mirrorOf> <!-- 正确的属性为 central --> | |
<name>Nexus aliyun</name> | |
<url>http://maven.aliyun.com/nexus/content/groups/public</url> | |
</mirror> |
或者
<!-- osgeo(伪)镜像 --> | |
<mirror> | |
<id>mirror-osgeo</id> | |
<mirrorOf>osgeo</mirrorOf> | |
<name>Mirror Osgeo</name> | |
<url>https://repo.osgeo.org/repository/release/</url> | |
</mirror> | |
<!-- 阿里云镜像 --> | |
<mirror> | |
<id>nexus-aliyun</id> | |
<mirrorOf>*</mirrorOf> <!-- 正确的属性为 central --> | |
<name>Nexus aliyun</name> | |
<url>http://maven.aliyun.com/nexus/content/groups/public</url> | |
</mirror> |
pom.xml
<repository> | |
<id>osgeo</id> | |
<name>OSGeo Release Repository</name> | |
<url>https://repo.osgeo.org/repository/release/</url> | |
<snapshots><enabled>false</enabled></snapshots> | |
<releases><enabled>true</enabled></releases> | |
</repository> |
# 正确配置
setting.xml
<!-- 阿里云镜像 --> | |
<mirror> | |
<id>nexus-aliyun</id> | |
<mirrorOf>central</mirrorOf> | |
<name>Nexus aliyun</name> | |
<url>http://maven.aliyun.com/nexus/content/groups/public</url> | |
</mirror> |
pom.xml
<repository> | |
<id>osgeo</id> | |
<name>OSGeo Release Repository</name> | |
<url>https://repo.osgeo.org/repository/release/</url> | |
<snapshots><enabled>false</enabled></snapshots> | |
<releases><enabled>true</enabled></releases> | |
</repository> |
# 四,如何知道是否需要配置仓库?
在 maven 的官网可以查询相关项目的信息,项目页面的标签栏标识了存储了该项目的仓库,只要是存储在中央仓库的项目都会标识 Central
标签,此时就不用配置新的仓库。
如果标签栏中没有标识 Central 仓库,说明中央仓库不包含该项目,需要配置新的仓库。
如对于 GeoTools 包,从图中我们可知,由于 Central 仓库不包含该包,我们就需要从其标签栏标识的 GeoSolutions 仓库、Geomajas 仓库、Boundless 仓库或 OSGeo 仓库拉取 GeoTools 包的资源