Maven中GeoTools的引入 - Maven 的 repository 与 mirror
Maven中GeoTools的引入 - Maven 的 repository 与 mirror
在Maven中引入GeoTools时找不到jar包,搜索了蛮久才明白是自己maven没有学明白,于是重学了一次maven,解决了这个问题。关键在于理解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>
然后添加GeoTools官方的仓库
<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执行的策略为:
- maven根据镜像配置文件(setting.xml)自上至下地依次查看所有的镜像,对每一个仓库依次进行匹配,并使用第一个匹配上的镜像。被镜像匹配的仓库,仓库的url被替换为镜像的url,没有匹配的仓库,url不变。
- 查询各仓库是否包请求的资源(项目),如都没有,则报错(如未找到),否则从第一个匹配上的仓库拉取资源。
三、解决方案与小技巧
- 不是所有的jar包都被包含在maven中央仓库中,如果中央仓库没有该资源,就需要配置第三方仓库(也可以理解为别人的公开私服)。maven中央仓库不包含GeoTools的相关资源,因此需要单独配置
OSGeo Release Repository
仓库。 - 阿里镜像和清华镜像只提供对中央仓库的资源镜像,其
mirrorOf
属性的值只能设置为central
,不要设置为* 。如果设置为*,则所有仓库的url都会被替换,对于本文的情况,就是本来应当发往OSGeo Release Repository
仓库的请求被发往阿里云镜像,而阿里云镜像不包含GeoTools的资源,自然是找不到了。正确的做法是每个镜像的mirrorOf
属性应与该镜像对应的仓库的id
属性保持一致。 - 还有一种骚操作(错误操作),就是在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包的资源。
参考资料:
https://en.wikipedia.org/wiki/Apache_Maven
https://www.cnblogs.com/shengulong/p/8295453.html maven的超级pom
如果这篇文章对你有用,可以点个赞再走哦~~