简介geotools-18.4相关Jar包集合面向需要在Java项目中集成GIS能力的开发者与空间数据分析人员。包内提供geotools核心库及配套依赖支持Shapefile、GeoJSON、GPKG、PostGIS等矢量/栅格数据读写并兼容WMS、WFS等OGC服务接口可满足地图渲染、空间分析、坐标转换等常见地理处理需求。资源共247个文件以229个Jar包为主体涵盖geotools各模块及数据库驱动、缓存组件等第三方依赖另含9个md、5个txt、3个html说明文档和1张结构示意图便于查阅与集成配置。整体大小约87.28MB已有1097人学习下载。对需要避开逐一查找依赖的开发者而言直接引入该集合可大幅减少构建环境时的版本匹配时间配合文档说明能更快理解模块用途与调用方式是搭建GeoTools开发环境的一套实用资源。1. GeoTools JAR包集合GIS开发中最容易被版本拖垮的一环在Java生态里处理GIS数据GeoTools是绕不开的开源库而我们常在网上下载到的geotools相关jar包集合本质上是它按功能拆分成几十个模块的产物。真正开始写代码时你会发现第一步不是业务逻辑而是把几十个JAR凑齐并让版本对齐这中间任何一个包版本不匹配程序都会在启动或运行时直接翻车。这篇文章把拆包、配依赖、做验证的实操经验整理出来适合刚开始集成GeoTools的Java开发者也适合需要离线部署或同ArcGIS配合做数据处理的项目组读完能少走很多弯路。2. 认识GeoTools的模块化体系核心包、数据包与渲染包2.1 三层的架构关系API、Main、Data各管什么第一次打开GeoTools的jar包集合时最容易懵的是看到gt-api、gt-main、gt-data、gt-shapefile、gt-render一堆相似的名字。这里必须先搞清三层关系因为后面所有依赖配置都建立在这三层上。最底层是gt-api它只定义接口比如FeatureSource、FeatureType、CoordinateReferenceSystem这些抽象契约本身不含实现。第二层是gt-main它负责把API接口落实到具体模型上比如FeatureImpl、GeometryFactory的路由等同时维护核心数据模型。第三层是gt-data它定义数据访问的统一抽象真正的文件读取逻辑往下由各自数据格式模块完成比如gt-shapefile处理shp文件、gt-geojson处理GeoJSON。理解了这三层后你就能明白为什么依赖里三个包经常同时出现gt-api提供类型定义gt-main提供模型实现gt-data提供访问入口三者协作才能组成一条完整的数据链路。单独拿一个gt-shapefile回来是不够的它运行时还会去调gt-main里的类。我在拆JAR包时的一个习惯是先把这三层核心包放进lib目录再逐个补业务用到的格式包遇到缺少依赖的ClassNotFoundException时按报错补包。2.2 常用模块清单读写、坐标系、渲染各取所需GeoTools的模块非常多但实际项目里高频使用的其实可以按功能分几组。这里把常见模块列成一张表方便对照自己的业务需求选包。模块JAR归属层级主要功能典型场景gt-shapefile数据层Shapefile.shp/.dbf/.shx读写与ArcGIS交换数据gt-geojson / gt-geojson-jackson数据层GeoJSON解析与生成Web端地图数据交互gt-referencing核心层坐标系定义与转换坐标投影变换gt-epsg-hsql核心层EPSG码数据库用EPSG:4326做WGS84转换gt-jts核心层JTS几何模型集成空间查询、缓冲区计算gt-render渲染层地图要素渲染服务端图片输出gt-swing渲染层Swing桌面地图组件桌面端预览工具gt-wms / gt-wfs数据层OGC服务客户端访问从服务端拉取地图或要素gt-jdbc数据层JDBC数据源抽象数据库空间字段读取gt-postgis数据层PostGIS方言支持PostGIS数据库读写gt-xml / gt-xsd数据层XML与XSD解析读写GML等XML格式这个清单不需要一次全引入。以最常见的读Shapefile→做投影变换→输出GeoJSON任务为例你只需要gt-api、gt-main、gt-data、gt-shapefile、gt-referencing、gt-epsg-hsql、gt-geojson以及它依赖的gt-jts这几个其他模块可以后续按需再补。这里要特别提醒一句GeoTools在较新的大版本里做过模块重组比如旧版的gt-geojson在部分新版本中被拆分为更细的模块gt-xml的解析逻辑也逐步迁移。所以网上找到的JAR包集合如果来源比较早与新版本代码混用会出现接口找不到的问题。我的建议是选定一个版本系列后所有模块尽量保持同版本不要跨版本混搭。提示GeoTools模块版本必须对齐选一个版本系列后不要混搭。2.3 版本号与依赖关系为什么一堆JAR不能随便删GeoTools的版本更新节奏比较稳定常见版本系列有21.x一直到30.x。每个正式版本发布时所有gt-*模块会同步打上相同版本号这是它最大的依赖特点模块间版本必须对齐否则jar包集合里会出现同一个类的多个版本JVM加载哪个全看classpath顺序这种问题排查起来特别玄学。另一个需要留意的点是gt-opengis这个老包。旧版本的GeoTools依赖gt-opengis提供OpenGIS接口定义而较新的版本已经把接口并入gt-api或相关模块。如果你从老项目里拷贝JAR包集合再往新项目里引用会出现典型的新代码找不到旧接口的编译错误。处理这种版本差异没有捷径只能逐个比对报错信息把老包换成当前版本对应的新包。此外还要注意第三方依赖的传递关系。GeoTools底层大量使用JTS几何库、HSQLDB数据库、Jackson JSON库等JAR包集合里一般会附带这些依赖包。但如果你自己的工程里也引用了这些依赖的旧版本就会产生冲突。我在实际项目中就遇到过Jackson版本不一致导致的GeoJSON解析异常后面在避坑章节里专门展开讲。3. 把这套JAR包集合工程化落地Maven配置与离线仓库搭建3.1 用Maven统一管理GeoTools依赖仓库与版本属性如果项目环境可以联网我最推荐的方式不是手动往classpath里塞JAR而是用Maven把依赖固定下来。这样版本号收口到一个属性里整个团队不会出现A机器能用、B机器报错的情况。第一步是配置Maven的settings.xml把GeoTools依赖的公共仓库加进去。常见做法是添加官方发布仓库和一个稳定镜像仓库因为GeoTools的稳定版本和部分扩展只从特定仓库分发。下面以占位地址示例实际使用时替换成你下载JAR包集合时对应的仓库地址settings profiles profile idgeotools-repos/id repositories repository idgeotools-release/id urlhttps://repo.example.com/geotools-release//url /repository repository idgeotools-mirror/id urlhttps://mirror.example.com/geotools//url /repository /repositories /profile /profiles activeProfiles activeProfilegeotools-repos/activeProfile /activeProfiles /settings这段配置里repository的id是本地标识url指向仓库地址。需要注意settings.xml是用户级配置放在用户主目录的.m2文件夹下修改后需要重启IDE或重新执行Maven命令才能生效。第二步是在项目的pom.xml里统一声明GeoTools版本。这里用一个property来定义版本号所有依赖都引用它方便后续升级时只改一处properties geotools.version30.2/geotools.version /properties dependencies dependency groupIdorg.geotools/groupId artifactIdgt-main/artifactId version${geotools.version}/version /dependency dependency groupIdorg.geotools/groupId artifactIdgt-shapefile/artifactId version${geotools.version}/version /dependency dependency groupIdorg.geotools/groupId artifactIdgt-referencing/artifactId version${geotools.version}/version /dependency dependency groupIdorg.geotools/groupId artifactIdgt-epsg-hsql/artifactId version${geotools.version}/version /dependency /dependencies这里以30.2为例实际使用哪个版本要结合你下载的JAR包集合来源和JDK版本确认。GeoTools对JDK环境有要求较新版本一般需要JDK 8以上部分新版本需要JDK 11或17如果本地JDK过低会出现类版本错误。使用版本属性${geotools.version}是Maven里管理多依赖同版本的标准做法后续升级只需改动一处property。3.2 离线环境手动安装JAR到本地Maven仓库很多内网开发环境无法访问外网仓库这时下载好的geotools相关jar包集合就派上用场了。你不需要把这些JAR直接复制进项目的lib目录更规范的做法是把它们逐个安装到本地Maven仓库让项目通过依赖坐标正常引用。手动安装的核心命令是mvn install:install-file。对于每个JAR需要提供文件路径、groupId、artifactId、version和packaging信息mvn install:install-file \ -Dfilegt-shapefile-30.2.jar \ -DgroupIdorg.geotools \ -DartifactIdgt-shapefile \ -Dversion30.2 \ -Dpackagingjar这条命令做的事是把指定的JAR文件写入本地仓库的org/geotools/gt-shapefile/30.2/目录并在该目录下生成对应的pom文件。注意这里是逐包安装如果JAR包集合里有30个模块就需要执行30次。为了省时间可以写个简单的shell循环遍历目录里的所有gt-*.jarfor jar in lib/gt-*.jar; do name$(basename $jar .jar) version30.2 mvn install:install-file \ -Dfile$jar \ -DgroupIdorg.geotools \ -DartifactId$name \ -Dversion$version \ -Dpackagingjar done参数方面-Dfile指定的是JAR的绝对或相对路径-DgroupId和-DartifactId会构成Maven坐标-Dversion必须与你要统一的版本号一致三个参数组合成唯一依赖标识。如果该JAR还依赖其他模块的pom元数据需要额外准备pom文件用-DpomFile参数指定否则Maven只能将该JAR当作无依赖的裸包处理。这里有个非常容易踩的坑手工安装的JAR如果缺少pom依赖信息后续构建项目时Maven不会自动传递依赖。比如只安装了gt-shapefile却没安装它内部的依赖项运行时会遇到ClassNotFoundException。所以内网环境里建议完整安装整个JAR包集合中所有模块和附带第三方依赖不要只装自己用到的几个。3.3 从JAR集合到可运行工程Classpath的组织方式如果你不想用Maven坚持传统方式直接引用JAR文件那Classpath的组织就要格外小心。一个通用的做法是把下载的JAR包集合解压后统一放入工程的lib目录同时把目录里所有JAR都加入构建路径。在IDEA或Eclipse里操作相对简单全选lib目录下的JAR文件添加到Libraries即可。但如果用命令行编译和运行需要手动拼接classpath我一般会先生成一个classpath文件echo $(ls -1 lib/*.jar | tr \n :) classpath.txt这个命令会把lib目录下所有JAR文件名拼成冒号分隔的classpath字符串写入classpath.txt文件。编译时配合javac的-cp参数使用运行时配合java的-cp参数使用。需要注意classpath末尾的冒号表示当前目录如果拼出来的字符串不带末尾冒号某些环境下会找不到默认包路径下的类。使用这种目录方式时lib目录里最好只放同一个版本的GeoTools及配套依赖不要出现两个不同版本的gt-main之类的同名文件。因为Classpath是按顺序加载类同名类先找到谁就用谁这种顺序带来的不确定性比Maven依赖冲突还难排查。为了减少手动维护成本我通常会把lib目录配合一个构建脚本使用。脚本先检查是否存在重复文件再执行编译、打包、运行三步这样每次拿到新的JAR包集合只要覆盖lib目录并重新跑一遍脚本就能快速验证包集合是否完整可用。4. 避坑排查版本冲突、EPSG数据库与坐标系转换4.1 启动报NoSuchMethodError版本混用的典型特征现象项目启动或执行某个空间操作时抛出的异常是java.lang.NoSuchMethodError报错信息指向某个geotools类的方法但代码编译时这个方法明明存在。原因JVM加载的某个JAR包版本与编译时不一致。比如classpath里同时存在旧版本gt-main和新版本gt-api新版本调用的方法在旧版本类里没有直接运行就炸了。这种错误在手动管理JAR包集合时尤其常见因为lib目录里如果混入了其他项目遗留的老包JVM按classpath顺序加载了错误版本。解决先做JAR包版本普查。在工程根目录执行依赖树命令把实际解析到的版本逐个确认mvn dependency:tree -Dincludesorg.geotools这条命令会列出工程中所有org.geotools相关依赖的版本。如果发现同一个模块出现多个版本就在pom.xml中排除旧版本或统一通过属性强制指定版本。对于手动管理classpath的情况直接检查lib目录下是否存在多个gt-*.jar的重名文件删除旧版本保留统一版本。现在合并代码前我都会检查一遍依赖树防止混入老包。4.2 EPSG数据库加载失败初始化坐标系时的黑匣子现象调用CRS.decode(EPSG:4326)或类似初始化坐标系的代码时抛出异常提示无法找到对应的坐标系定义或直接报出关于epsg相关文件的错误。原因GeoTools的坐标系定义依赖EPSG数据库而EPSG数据库本身是以HSQLDB文件形式存放在gt-epsg-hsql这个JAR包中的。如果你的工程没有引入gt-epsg-hsql或者JAR包集合里缺少这个模块坐标系解码就会失败。另一个常见原因是某些精简版JAR包集合把EPSG数据文件单独拆出来但使用时没有放到classpath的资源路径下。解决确认引入了gt-epsg-hsql模块且版本与其他gt包一致。如果使用Maven检查依赖里是否有这一项如果手动管理classpath确认lib目录里存在gt-epsg-hsql这个JAR。还需要注意有些非官方EPSG码比如国内测绘行业常用的坐标系需要确认当前版本GeoTools是否内置该码。如果内置版本里没有就要改用CRS.parseWKT传入完整WKT字符串定义String wkt GEOGCS[\Custom CRS\,DATUM[\...\],...]; CoordinateReferenceSystem crs CRS.parseWKT(wkt);这里使用parseWKT可以绕过EPSG码表限制。很多从ArcGIS导出的数据使用自定义坐标系WKT描述往往与标准EPSG码有细微差别读出来的坐标系虽然都是WGS84但底层参数不一致会导致后面的转换结果偏差这个坑在4.3节接着讲。4.3 坐标系转换结果差几百米WKT与EPSG码的选择现象用GeoTools做坐标转换把WGS84经纬度转换到Web Mercator或某个投影坐标结果和ArcGIS里转换出来的数值相差几百米甚至更多。原因这个翻车现场通常是坐标系定义不一致导致的。GeoTools里CRS.decode(EPSG:4326)使用的是标准EPSG定义而ArcGIS工程文件里使用的可能是经过自定义参数调整的坐标系比如基准面参数被改过。两边虽然都叫WGS 84但数学定义不同转换结果自然对不上。另一个常见原因是源数据本身不是WGS84坐标系却按WGS84去解码了。解决在做转换前先明确数据的原始坐标系定义。如果是来自ArcGIS的数据建议优先读取它的.prj文件里的WKT描述用CRS.parseWKT而不是CRS.decode来构建坐标系。转换前还可以做一个验证取一个已知坐标点分别用两种方式定义源坐标系去转换对比结果是否一致。下面是一个常见的转Web Mercator的示例CoordinateReferenceSystem sourceCRS CRS.decode(EPSG:4326); CoordinateReferenceSystem targetCRS CRS.decode(EPSG:3857); MathTransform transform CRS.findMathTransform(sourceCRS, targetCRS, true);代码里的第三个参数true表示使用长度归一化即做精确转换。如果把true改成false某些情况下会启用快速近似算法精度下降但性能提升。对于地图瓦片或常规可视化近似算法通常够用但对于GIS量算、面积统计这种对精度敏感的场景必须保持true。这个参数是很多新手容易忽略的建议默认写true。4.4 JTS版本冲突几何类型转换时的翻车现场现象程序运行到某个构建几何或空间分析的地方报出com.vividsolutions.jts.geom相关类错误或者java.lang.NoClassDefFoundError提示找不到Geometry类。原因GeoTools在较新版本中使用了org.locationtech.jts作为几何库而很多老项目或第三方库还在用com.vividsolutions.jts两者包路径不同但类名相似。如果classpath里同时存在两套JTSGeoTools默认使用org.locationtech.jts而你的代码里import了com.vividsolutions.jts两套几何对象互相不兼容强制转换时就会出问题。解决统一使用org.locationtech.jts的类并在Maven依赖中排除旧版JTS坐标。可以在pom里做如下排除dependency groupIdorg.geotools/groupId artifactIdgt-main/artifactId version${geotools.version}/version exclusions exclusion groupIdcom.vividsolutions/groupId artifactIdjts/artifactId /exclusion /exclusions /dependency这段配置的作用是告诉Maven在解析gt-main的传递依赖时排除com.vividsolutions.jts这个旧库。手工管理JAR时直接确保lib目录里没有com.vividsolutions开头的JAR文件即可。如果第三方库必须依赖旧版JTS那就只能在调用边界做类型转换避免把两种Geometry混在一个集合里操作。5. 验证工具用最小Shapefile读取Demo检查JAR包完整性拿到JAR包集合后不要急着写业务代码先用一个最小的读写程序验证包是否完整可用。我习惯用Shapefile读取作为验证场景因为Shapefile是ArcGIS/GeoJSON互操作里的高频格式能覆盖核心层、数据层、坐标系层三大部分。先准备一个Maven工程的pom引入必要模块properties geotools.version30.2/geotools.version /properties dependencies dependency groupIdorg.geotools/groupId artifactIdgt-main/artifactId version${geotools.version}/version /dependency dependency groupIdorg.geotools/groupId artifactIdgt-shapefile/artifactId version${geotools.version}/version /dependency dependency groupIdorg.geotools/groupId artifactIdgt-referencing/artifactId version${geotools.version}/version /dependency dependency groupIdorg.geotools/groupId artifactIdgt-epsg-hsql/artifactId version${geotools.version}/version /dependency /dependencies接着写一个读取Shapefile并输出坐标系和要素数量的Demoimport org.geotools.data.FileDataStore; import org.geotools.data.FileDataStoreFinder; import org.geotools.data.simple.SimpleFeatureSource; import org.geotools.referencing.CRS; import org.opengis.referencing.crs.CoordinateReferenceSystem; import java.io.File; public class ShpValidate { public static void main(String[] args) throws Exception { File file new File(args[0]); FileDataStore store FileDataStoreFinder.getDataStore(file); SimpleFeatureSource source store.getFeatureSource(); CoordinateReferenceSystem crs source.getSchema() .getCoordinateReferenceSystem(); String epsg CRS.lookupIdentifier(crs, true); System.out.println(要素类型: source.getSchema().getTypeName()); System.out.println(坐标系: (epsg ! null ? epsg : 自定义/未识别)); System.out.println(要素数量: source.getFeatures().size()); store.dispose(); } }这段代码先通过FileDataStoreFinder定位并打开Shapefile然后从数据源的schema里取出坐标系定义再用CRS.lookupIdentifier尝试反查EPSG码。如果JAR包不完整通常会在store或getSchema这一步抛出异常。如果能正常输出要素数量和EPSG码说明核心包、Shapefile包、坐标系包都已正确加载。代码中store.dispose()用来释放文件句柄验证程序跑完不释放会导致Windows下文件被占用后续重复读取会失败。验证程序的输入参数是Shapefile路径使用方式为java -cp ... ShpValidate /path/to/file.shp。如果输出里坐标系显示为自定义/未识别优先检查是否缺少gt-epsg-hsql模块用4.2节里的方式补充。如果要素数量为0先确认Shapefile本身在ArcGIS里是否能打开排除数据文件损坏的情况。从那以后我每下载一套新的JAR包集合都会先跑这个最小Demo再决定是否引入正式项目这个习惯帮我挡掉了不少配置上的冤枉路。希望这个思路能帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?