^ 关注我,带你一起学GIS ^
前言
❝在现代GIS开发中,OpenLayers 作为强大的前端地图库,与后端服务的无缝集成是实现动态空间数据可视化的关键。GeoJSON 作为一种轻量级的地理数据交换格式,因其结构清晰、兼容性强,成为前后端传输空间数据的首选方案。
本文将详细介绍如何通过 OpenLayers 从后端服务(Spring Boot)高效加载 GeoJSON 数据。
1. 搭建SpringBoot后端服务
开发环境
时间:2025年
GeoTools:34-SNAPSHOT
IDE:IDEA2025.1.2
JDK:17
创建好SpringBoot
项目后配置数据库连接信息:
spring.application.name=geotools-boot
# src/main/resources/application.properties
server.port=8080
spring.datasource.url=jdbc:postgresql://localhost:5432/geodata?useSSL=false
spring.datasource.username=postgres
spring.datasource.password=123456
spring.jpa.hibernate.ddl-auto=update
在pom.xml
文件中安装GeoTools
所需依赖。
<!-- GeoTools依赖 -->
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-main</artifactId>
<version>${geotools.version}</version>
</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-xml</artifactId>
<version>${geotools.version}</version>
</dependency>
<dependency>
<groupId>org.geotools.xsd</groupId>
<artifactId>gt-xsd-kml</artifactId>
<version>${geotools.version}</version>
</dependency>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-geojson</artifactId>
<version>${geotools.version}</version>
</dependency>
<dependency>
<groupId>org.geotools.jdbc</groupId>
<artifactId>gt-jdbc-postgis</artifactId>
<version>${geotools.version}</version>
</dependency>
<!-- PostgreSQL 驱动 -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.7.3</version>
</dependency>
创建省级行政区实体对象Province
public class Province {
@Setter
@Getter
public Integer gid;
@Setter
@Getter
public String name;
@Setter
@Getter
public String layer;
@Setter
@Getter
public BigDecimal kind;
@Setter
@Getter
public BigDecimal admincode;
@Setter
@Getter
public String geom;
}
添加读取PostGIS
空间数据实现类,使用GeometryJSON
类将几何字段数据转换为GeoJSON数据。
@Service
public class PgService {
public List<Province> readSpatialData() throws Exception{
// 连接PostGIS数据库
Map<String, Object> pgParams = new HashMap<>();
pgParams.put(PostgisNGDataStoreFactory.DBTYPE.key, "postgis");
pgParams.put(PostgisNGDataStoreFactory.HOST.key, "localhost");
pgParams.put(PostgisNGDataStoreFactory.PORT.key, "5432");
pgParams.put(PostgisNGDataStoreFactory.DATABASE.key, "geodata");
pgParams.put(PostgisNGDataStoreFactory.USER.key, "postgres");
pgParams.put(PostgisNGDataStoreFactory.PASSWD.key, "123456");
pgParams.put(PostgisNGDataStoreFactory.SCHEMA.key, "public"); // 明确指定schema
pgParams.put(PostgisNGDataStoreFactory.EXPOSE_PK.key, true); // 暴露主键
DataStore dataStore = DataStoreFinder.getDataStore(pgParams);
// 数据库表名称
String typeName = "province";
SimpleFeatureSource featureSource = dataStore.getFeatureSource(typeName);
// 返回数据列表
List<Province> provinces = new ArrayList<>();
try(FeatureIterator<SimpleFeature> features = featureSource.getFeatures().features()) {
while (features.hasNext()) {
SimpleFeature feature = features.next();
Province province = new Province();
// 添加要素
province.setGid((Integer) feature.getAttribute("gid"));
province.setName((String) feature.getAttribute("name"));
province.setLayer((String) feature.getAttribute("layer"));
province.setAdmincode((BigDecimal) feature.getAttribute("admincode"));
Object geometry = feature.getAttribute("geom");
// 读取几何字段数据为GeoJSON字符串
GeometryJSON geometryJSON = new GeometryJSON();
StringWriter writer = new StringWriter();
geometryJSON.write((Geometry) geometry,writer);
String jsonString = writer.toString();
province.setGeom(jsonString);
provinces.add(province);
}
}catch(Exception e){
e.printStackTrace();
}
dataStore.dispose();
return provinces;
}
}
编写控制类ReadPgController
读取空间数据列表接口,使用@CrossOrigin(origins = "*")
注解允许前端访问,不然会报跨域。
/**
* 获取空间数据列表
*/
@CrossOrigin(origins = "*") // 或指定前端地址
@RestController
public class ReadPgController {
@Autowired
private PgService pgService;
@GetMapping("/spatial/list")
public List<Province> getProviceList() throws Exception{
return pgService.readSpatialData();
}
}
2. 使用OpenLayers加载数据
具体使用情况请参考之前的文章:OpenLayers 加载GeoJSON的五种方式
在前端中读取后端数据可以使用原生XMLHttpRequest()
请求实现,也可以通过引入第三方库Axios
实现,本文使用更简单的fetch API
请求。
// 后端服务地址
const JSON_URL = "http://127.0.0.1:8080/spatial/list"
fetch(JSON_URL)
.then(response => response.json()
.then(result => {
// console.log(result)
// 读取Feature要素
const features = result.map(item => {
const feat = {}
feat.type = "Feature"
feat.geometry = JSON.parse(item.geom)
feat.properties = item
feat.properties.color = `hsl(${Math.floor(Math.random() * 360)}, 100%, 50%)`
const feature = new ol.format.GeoJSON().readFeature(feat)
return feature
})
const vectorSource = new ol.source.Vector({
features: features,
format: new ol.format.GeoJSON()
})
// 行政区矢量图层
const regionLayer = new ol.layer.Vector({
source: vectorSource,
style: {
'fill-color': ['string', ['get', 'color'], '#eee'],
}
})
regionLayer.set("title", "云南行政区")
map.addLayer(regionLayer)
map.getView().setCenter([108.76623301275802, 34.22939602197002])
map.getView().setZoom(4.5)
)
使用GeoJSON()
构造矢量数据源,所以需要使用readFeature
方法将Feature Object
对象转换为OpenLayers Feature
对象。后端返回的几何字段geom
为字符串类型,所以使用JSON.parse
方法将其转换为JSON
对象。
在要素属性中添加color
属性,设置其值为hsl
随机颜色值。feat.properties.color = `hsl(${Math.floor(Math.random() * 360)}, 100%, 50%)`
// 读取Feature要素
const features = result.map(item => {
const feat = {}
feat.type = "Feature"
feat.geometry = JSON.parse(item.geom)
feat.properties = item
feat.properties.color = `hsl(${Math.floor(Math.random() * 360)}, 100%, 50%)`
const feature = new ol.format.GeoJSON().readFeature(feat)
return feature
})
设置行政区填充样式,'fill-color': ['string', ['get', 'color'], '#eee']
为OpenLayers样式表达式写法,表示从color
属性中获取颜色值填充要素样式,如果未获取到,则使用默认颜色值'#eee'
填充。
具体可以参考文章:OpenLayers样式表达式。
// 行政区矢量图层
const regionLayer = new ol.layer.Vector({
source: vectorSource,
style: {
'fill-color': ['string', ['get', 'color'], '#eee'],
}
})
表现效果如下:
❝
OpenLayers示例数据下载,请在公众号后台回复:ol数据
全国信息化工程师-GIS 应用水平考试资料,请在公众号后台回复:GIS考试
❝
GIS之路公众号已经接入了智能助手,欢迎大家前来提问。
欢迎访问我的博客网站-长谈GIS:
http://shanhaitalk.com
都看到这了,不要忘记点赞、收藏+关注 哦!
本号不定时更新有关 GIS开发 相关内容,欢迎关注