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
junit
junit
4.11
test
org.geotools
gt-shapefile
${geotools.version}
org.geotools
gt-swing
${geotools.version}
org.geotools
gt-main
${geotools.version}
org.geotools.jdbc
gt-jdbc-postgis
${geotools.version}
org.geotools
gt-metadata
${geotools.version}
org.geotools
gt-referencing
${geotools.version}
org.geotools
gt-geojson
${geotools.version}
org.geotools
gt-epsg-hsql
${geotools.version}
log4j
log4j
1.2.17
com.alibaba
fastjson
1.2.47
commons-io
commons-io
2.6
org.postgis
postgis-driver
1.0
第二步:创建PostGis数据源操作对象,相当于JDBC 数据源
public class PostgisDataStore {
private static Logger logger = Logger.getLogger(PostgisDataStore.class);
private static DataStore postgisDataStore = null;
private static String dbtype = null;
private static String host = null;
private static String port = null;
private static String database = null;
private static String schema = null;
private static String username = null;
private static String password = null;
public PostgisDataStore() {
}
public static DataStore getInstance() {
if (postgisDataStore == null) {
Map params = new HashMap();
params.put(PostgisNGDataStoreFactory.DBTYPE.key, dbtype);
params.put(PostgisNGDataStoreFactory.HOST.key, host);
params.put(PostgisNGDataStoreFactory.PORT.key, new Integer(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 (IOException e) {
logger.error("\nPostgisDataStore 初始化geotools中的 Datastore失败\n");
logger.error(e.getMessage());
}
}
return postgisDataStore;
}
}
以上代码仅供参考,如需在实战中使用,还是尽可能利用已有的连接池技术提高应用性能。
第三步:准备待带入的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
*/
public static boolean importGeojson(String geojsonpath, String tablename) throws IOException {
if (!validateGeojson(geojsonpath, true)) return false;
DataStore pgDatastore = postgisDataStore.getInstance();
FeatureJSON featureJSON = new FeatureJSON();
FeatureCollection featureCollection = featureJSON.readFeatureCollection(new FileInputStream(geojsonpath));
SimpleFeatureType geojsontype = (SimpleFeatureType) featureCollection.getSchema();
SimpleFeatureTypeBuilder typeBuilder = new SimpleFeatureTypeBuilder();
typeBuilder.init(geojsontype);
typeBuilder.setName(tablename);
SimpleFeatureType newtype = typeBuilder.buildFeatureType();
pgDatastore.createSchema(newtype);
FeatureIterator iterator = featureCollection.features();
FeatureWriter featureWriter = pgDatastore.getFeatureWriterAppend(tablename, Transaction.AUTO_COMMIT);
while (iterator.hasNext()) {
Feature feature = iterator.next();
SimpleFeature simpleFeature = featureWriter.next();
Collection properties = feature.getProperties();
Iterator propertyIterator = properties.iterator();
while (propertyIterator.hasNext()) {
Property property = propertyIterator.next();
simpleFeature.setAttribute(property.getName().toString(), property.getValue());
}
featureWriter.write();
}
iterator.close();
featureWriter.close();
pgDatastore.dispose();
return true;
}
第五步:测试调用
PostgisDataStore postgisDataStore = new PostgisDataStore();
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);
boolean flag = 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上将代码下载下来进行调试。