GeoJson是一种对各种地理数据结构进行编码的格式,基于json的地理空间信息数据交换格式。GeoJson对象可以用来表示几何,特征或者特征集合。支持地理点、线、面、多点、多线、多面及几何集合。GeoJson不是本文的重点,因此不再赘述。
PostGIS是在对象关系型数据库PostgreSQL上增加了存储管理空间数据的能力的开源GIS数据库。本文的例子不能直接运行在PostgreSql的数据库上,需要装扩展依赖才行(具体可参考某度的详细教程)。
本文将重点介绍如何基于GeoTools将GeoJson数据导入到PostGis中,并通过数据库客户端软件查询到导入结果。
本实例运行环境:
1:win7+jdk8+GeoTools 24+POSTGIS: 3.1+PostgreSQL 9.6.14
第一步:准备GeoTools依赖的包,详情见pom.xml
<dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.11</version><scope>test</scope></dependency><dependency><groupId>org.geotools</groupId><artifactId>gt-shapefile</artifactId><version>${geotools.version}</version></dependency><dependency><groupId>org.geotools</groupId><artifactId>gt-swing</artifactId><version>${geotools.version}</version></dependency><dependency><groupId>org.geotools</groupId><artifactId>gt-main</artifactId><version>${geotools.version}</version></dependency><dependency><groupId>org.geotools.jdbc</groupId><artifactId>gt-jdbc-postgis</artifactId><version>${geotools.version}</version></dependency><dependency><groupId>org.geotools</groupId><artifactId>gt-metadata</artifactId><version>${geotools.version}</version></dependency><dependency><groupId>org.geotools</groupId><artifactId>gt-referencing</artifactId><version>${geotools.version}</version></dependency><dependency><groupId>org.geotools</groupId><artifactId>gt-geojson</artifactId><version>${geotools.version}</version></dependency><dependency><groupId>org.geotools</groupId><artifactId>gt-epsg-hsql</artifactId><version>${geotools.version}</version></dependency><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency><!-- https://mvnrepository.com/artifact/com.alibaba/fastjson --><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.47</version></dependency><!--非必需,简化I/O操作--><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.6</version></dependency><dependency><groupId>org.postgis</groupId><artifactId>postgis-driver</artifactId><version>1.0</version></dependency></dependencies>
第二步:创建PostGis数据源操作对象,相当于JDBC 数据源
publicclassPostgisDataStore { privatestaticLoggerlogger=Logger.getLogger(PostgisDataStore.class); privatestaticDataStorepostgisDataStore=null; privatestaticStringdbtype=null; privatestaticStringhost=null; privatestaticStringport=null; privatestaticStringdatabase=null; privatestaticStringschema=null; privatestaticStringusername=null; privatestaticStringpassword=null; publicPostgisDataStore() { } publicstaticDataStoregetInstance() { if (postgisDataStore==null) { Map<String, Object>params=newHashMap<String, Object>(); params.put(PostgisNGDataStoreFactory.DBTYPE.key, dbtype); params.put(PostgisNGDataStoreFactory.HOST.key, host); params.put(PostgisNGDataStoreFactory.PORT.key, newInteger(port)); params.put(PostgisNGDataStoreFactory.DATABASE.key, database); params.put(PostgisNGDataStoreFactory.SCHEMA.key, schema); params.put(PostgisNGDataStoreFactory.USER.key, username); params.put(PostgisNGDataStoreFactory.PASSWD.key, password); try { postgisDataStore=DataStoreFinder.getDataStore(params); logger.info("\nPostgisDataStore 初始化geotools中的 Datastore成功\n"); } catch (IOExceptione) { logger.error("\nPostgisDataStore 初始化geotools中的 Datastore失败\n"); logger.error(e.getMessage()); } } returnpostgisDataStore; } }
以上代码仅供参考,如需在实战中使用,还是尽可能利用已有的连接池技术提高应用性能。
第三步:准备待带入的GeoJson数据,以Line为例
{ "type": "FeatureCollection", "features": [ { "type": "Feature", "properties": { "name": "north", "linedesc": "A" }, "geometry": { "type": "LineString", "coordinates": [ [ 476.7884016036988, 39.9663655061331 ], [ 476.7959976196289, 39.96679309103126 ], [ 476.80423736572268, 39.96613526700328 ] ] } } ] }
第四步:将GeoJson数据写入到数据库中,关键代码如下:
/** * geojson 文件导入的Postgis数据库 * * @param geojsonpath geojson文件存储路径,包括文件拓展名.json或者.geojson * @param tablename 自定义存储到postgis数据库存储的表的名称 * @return 导入结果 * @throws IOException */publicstaticbooleanimportGeojson(Stringgeojsonpath, Stringtablename) throwsIOException { if (!validateGeojson(geojsonpath, true)) returnfalse; DataStorepgDatastore=postgisDataStore.getInstance(); FeatureJSONfeatureJSON=newFeatureJSON(); FeatureCollectionfeatureCollection=featureJSON.readFeatureCollection(newFileInputStream(geojsonpath)); SimpleFeatureTypegeojsontype= (SimpleFeatureType) featureCollection.getSchema(); SimpleFeatureTypeBuildertypeBuilder=newSimpleFeatureTypeBuilder(); typeBuilder.init(geojsontype); typeBuilder.setName(tablename); SimpleFeatureTypenewtype=typeBuilder.buildFeatureType(); pgDatastore.createSchema(newtype); FeatureIteratoriterator=featureCollection.features(); FeatureWriter<SimpleFeatureType, SimpleFeature>featureWriter=pgDatastore.getFeatureWriterAppend(tablename, Transaction.AUTO_COMMIT); while (iterator.hasNext()) { Featurefeature=iterator.next(); SimpleFeaturesimpleFeature=featureWriter.next(); Collection<Property>properties=feature.getProperties(); Iterator<Property>propertyIterator=properties.iterator(); while (propertyIterator.hasNext()) { Propertyproperty=propertyIterator.next(); simpleFeature.setAttribute(property.getName().toString(), property.getValue()); } featureWriter.write(); } iterator.close(); featureWriter.close(); pgDatastore.dispose(); returntrue; }
第五步:测试调用
PostgisDataStorepostgisDataStore=newPostgisDataStore(); PostgisDataStore.setHost("127.0.0.1"); PostgisDataStore.setPort("5432"); // 扩展数据库类型,读取postgis该参数类型设置为postgis// 其余设置对应的数据库类型,要求jdbc支持并且引入相关库PostgisDataStore.setDbtype("postgis"); PostgisDataStore.setDatabase("postgis_31_sample"); PostgisDataStore.setSchema("public"); PostgisDataStore.setUsername("asus"); PostgisDataStore.setPassword("postgres"); PostgisUtility.setPostgisDataStore(postgisDataStore); booleanflag=PostgisUtility.importGeojson("D:\\wzh_workspace_20210320\\geotools4postgis\\src\\main\\java\\iwuang\\line.geojson", "wzh_line2"); System.out.println(flag);
使用数据客户端软件打开后可以查询到导入的数据
总结,通过以上程序可以实现GeoJson数据的导入,如果遇到数据库连不上,请查找是不是数据连接信息没有正确配置,比如用户名密码等有没有正确输入。应用程序处理通用序列图如下:
本文代码参考至https://github.com/yieryi/geotools4postgis,有兴趣的各位可以到github上将代码下载下来进行调试。