26 KiB
title | date | author | tags | categories | |||||
---|---|---|---|---|---|---|---|---|---|
服务的加载 | 2020-11-18 | ac |
|
|
1. ol中的服务
对于OGC规范的数据显示,OpenLayers 封装了一些数据源和解析器,如ol.source.WMTS
、ol.source.ImageWMS
、ol.source.TileWMS
、ol.format.WFS
等。这些OGC规范的数据显示,与其他类型的数据加载方式类似,通过图层(Layer)+ 数据源(Source)的方式加载显示,在实例化数据对象时,设置请求OGC服务的URL地址及相关参数。
服务类型 | 接口 | 接口描述 | 类 |
---|---|---|---|
WMTS | GetTile | 返回单张瓦片 | ol.layer.Tile +ol.source.WMTS |
WMS | GetMap | 返回指定范围内的地图图片 | ol.layer.Image +ol.source.ImageWMS 或ol.layer.Tile +ol.source.TileWMS |
WFS | GetFeature | 返回指定格式(GML或GeoJSON)的矢量数据 | ol.layer.Vector +ol.source.Vector |
下面以GeoServer地图服务器自带提供的Demo数据服务为示例数据,演示OGC服务的加载:

1.1 WMTS服务
为了更快的将地图数据在前端显示,可以为一些数据不会变更或变动较小的服务创建地图缓存(Cache)。WMTS是一种采用图像金字塔的方式将地图服务按照预先设置的某种切图策略创建的地图缓存服务。

切图原理
1.基础概念
- Scale:比例尺,即地图上的一厘米代表着实际上的多少厘米。原 scale 中表示的实际单位是厘米
- Resolution:分辨率,实际含义代表当前地图范围内,1像素代表多少地图单位(地图单位/像素),地图单位取决于数据本身的空间参考。
- dpi :代表每英寸的像素数
2.地图比例尺的换算
在配置切片策略的时候,对金字塔的每个级别(切图的比例尺参数)都需要一个level 和 resolution ,这些是用于计算屏幕上1像素代表的实际距离计算。
假设地图的坐标单位是米,dpi为96(ArcGIS中dpi默认是96, OGC标准输出的resolution is 90 DPI(25.4/0.28))
1英寸=2.54厘米; 1英寸=96像素;
最终换算的单位是米;
如果当前地图比例尺为1:125000000,则代表图上1米等于实地125000000米;
米和像素间的换算公式:
1英寸=0.0254米=96像素
1像素=0.0254/96 米
则根据1:125000000比例尺,图上1像素代表实地距离是 125000000*0.0254/96 = 33072.9166666667米 , 即 resolution = scale*0.0254/dpi
3.瓦片行列号的计算
假设,地图的切图原点(通常是地图的左上角(minx,maxy))是(x0,y0),地图的瓦片大小是tileSize,地图屏幕上1像素代表的实际距是resolution。计算坐标点(x,y)所在的瓦片的行列号的公式是:
加载示例
<!doctype html>
<html >
<head>
<link rel="stylesheet" href="css/ol.css" type="text/css">
<style>
.map {
height: 90vh;
width: 100%;
}
</style>
<script src="lib/ol.js"></script>
<title>OpenLayers example</title>
<meta charset="UTF-8">
</head>
<body>
<h2>OGC WMTS服务:加载GeoServer的WMTS服务</h2>
<div id="map" class="map"></div>
<script type="text/javascript">
var nyc = [-73.92722,40.774221];
var map = new ol.Map({
target:"map",
layers:[
new ol.layer.Tile({
source: new ol.source.OSM()
})
],
view:new ol.View({
center:ol.proj.fromLonLat(nyc),
zoom:12
})
});
//分辨率数组,应与gridset中的Tile Matrix Set的Pixel Size保持一致
var resolutions = [0.703125, 0.3515625, 0.17578125, 0.087890625, 0.0439453125, 0.02197265625, 0.010986328125,0.0054931640625, 0.00274658203125, 0.001373291015625, 6.866455078125E-4, 3.4332275390625E-4,1.71661376953125E-4, 8.58306884765625E-5, 4.291534423828125E-5, 2.1457672119140625E-5, 1.0728836059570312E-5,5.364418029785156E-6, 2.682209014892578E-6, 1.341104507446289E-6, 6.705522537231445E-7, 3.3527612686157227E-7];
//矩阵标识列表,应与gridset中的Tile Matrix Set的Name保持一致
var matrixIds = ['EPSG:4326:0', 'EPSG:4326:1', 'EPSG:4326:2', 'EPSG:4326:3', 'EPSG:4326:4','EPSG:4326:5', 'EPSG:4326:6', 'EPSG:4326:7', 'EPSG:4326:8', 'EPSG:4326:9', 'EPSG:4326:10', 'EPSG:4326:11','EPSG:4326:12', 'EPSG:4326:13', 'EPSG:4326:14', 'EPSG:4326:15', 'EPSG:4326:16', 'EPSG:4326:17', 'EPSG:4326:18','EPSG:4326:19', 'EPSG:4326:20', 'EPSG:4326:21'];
var wmtsSource = new ol.source.WMTS({
url: 'http://localhost:8080/geoserver/gwc/service/wmts',
layer: 'tiger:tiger_roads',
matrixSet: 'EPSG:4326',
format: 'image/png',
projection: 'EPSG:4326',
//瓦片网格对象,即切图方案gridset的配置
tileGrid: new ol.tilegrid.WMTS({
extent: [-180,-90, 180, 90],//范围
tileSize: [256, 256],
origin: [-180,90], //切图原点(左上角:minx,maxy)
resolutions: resolutions,
matrixIds: matrixIds
}),
tileLoadFunction:function(imageTile, src) {
imageTile.getImage().src = src;
}
});
var wmtsLayer = new ol.layer.Tile({
source: wmtsSource,
//设置图层的边界,坐标参考与view中保持一致
extent:ol.proj.transformExtent([-74.02722,40.684221,-73.907005,40.878178],
"EPSG:4326","EPSG:3857")
});
map.addLayer(wmtsLayer);
</script>
</body>
</html>

解析:
通过创建ol.source.WMTS
实例,配置WMTS服务信息:
-
url:WMTS服务的地址
-
layer:服务的图层名或图层组名,格式是:命名空间+“:”+图层名|图层组名
-
matrixSet:切图策略的名称(GridSet的名称)
-
format:指定响应瓦片的格式,可以在图层信息中的“Tile Caching”中查看,
image/jpeg是只有[r,g,b]三个通道的,但image/png是有[r,g,b,a]四个通道的可以实现背景透明的效果
-
projection:配置服务所属的坐标参考。如果与view中的参考不同会进行重投影
-
tileGrid:瓦片网格对象,即是服务的切图方案的配置对象,应与服务对应的GridSet保持一致,才能正确的计算瓦片的级别和行列号。
-
tileLoadFunction:瓦片加载函数。默认是上述的脚本,是WMTS服务的GetTile请求URL。
在创建Tile图层实例时,增加Extent参数限制数据源加载瓦片的边界(服务图层的边界),避免出现行列号索引越界的400的请求。

1.2 WMS服务
WMS服务是一个动态数据或用户定制地图(需结合SLD标准)的理想解决方案。它可以动态生成当前地图视图范围内的图层服务的图片并响应到前端供地图展示,还提供根据地图上像素点获取图层要素信息的查询操作。
接口 | 描述 |
---|---|
GetCapabilities | 获取服务中的要素类及支持的操作 |
GetMap | 获取服务器生成的地图图片 |
GetFeatureInfo | 根据地图上的像素点获取详细的要素信息 |
GetMap操作
核心参数指定要在地图上显示的一个或多个图层和样式,地图范围的边界框,目标空间参考系统以及输出的宽度,高度和格式。
参数 | 是否必须 | 说明 |
---|---|---|
version | 是 | WMS服务版本,默认1.3.0 |
request=GetMap | 是 | 请求类型 |
layers | 是 | 逗号分隔的一个或多个图层列表 |
styles | 是 | 逗号分隔的一个或多个图层的样式列表。 |
crs | 是 | 坐标参考(1.1.1是srs,1.3.0是crs) |
bbox | 是 | CRS下的边框角(左下,右上) |
width | 是 | 输出的地图图片宽度 |
height | 是 | 输出的地图图片高度 |
format | 是 | 指定请求响应的输出格式 |
transparent | 图层是否透明,默认true | |
bgcolor | 响应图片的背景色(十六进制的rgb颜色值) | |
exceptions | 异常的输出格式,默认XML | |
time | ||
elevation |
layers参数中的值和styles样式参数中的值之间存在一一对应关系。
版本差异
版本1.1.1和1.3.0之间的主要区别是:
- 在1.1.1中,使用EPSG名称空间指定的地理坐标系被定义为具有经度/纬度的轴顺序。在1.3.0中,顺序为纬度/经度。 2. 在GetMap操作中,srs参数在1.3.0中被crs替换。无论版本如何,GeoServer都支持这两个参数。 3. 在GetFeatureInfo操作的x和y参数在1.3.0版中被称为i和j。除处于CITE兼容模式下外,GeoServer均支持两个参数,而与版本无关。
geoserver/wms?VERSION=1.1.1&REQUEST=GetMap&SRS=epsg:4326&BBOX=-180,-90,180,90&…
geoserver/wms?VERSION=1.3.0&REQUEST=GetMap&CRS=epsg:4326&BBOX=-90,-180,90,180&…
请求示例

在OpenLayers中加载WMS服务可以使用以下两种方式进行加载:
-
ol.layer.Image
+ol.source.ImageWMS
-
ol.layer.Tile
+ol.source.TileWMS
使用Tile
的方式加载时,响应回来的瓦片会被浏览器缓存,当地图视口内的WMS服务被缓存后不会重复请求已经缓存的图片,但存在的问题是,如果首次发送的GetMap请求一直没有响应图片,后续将不会再发送该区域范围内的GetMap请求。在这种情况下,相比Tile
的方式,ImageWMS的方式是渲染返回的单张图片会有更好的制图效果。
<!doctype html>
<html >
<head>
<link rel="stylesheet" href="css/ol.css" type="text/css">
<style>
.map {
height: 400px;
width: 100%;
}
</style>
<script src="lib/ol.js"></script>
<title>OpenLayers example</title>
<meta charset="UTF-8">
</head>
<body>
<h2>OGC WMS服务,方式一:ol.layer.Image + ol.source.ImageWMS</h2>
<div id="map" class="map"></div>
<script type="text/javascript">
var layers = [
new ol.layer.Tile({
source: new ol.source.OSM()
}),
new ol.layer.Image({
source:new ol.source.ImageWMS({
url: 'http://localhost:8080/geoserver/tiger/ows',
params: {
//WIDTH, HEIGHT, BBOX and CRS (SRS for WMS version < 1.3.0) 将被动态设置.
'LAYERS': 'tiger:tiger_roads',
'VERSION':'1.1.1'//默认1.3.0,GeoServer为WMS提供1.1.1和1.3.0版本的支持
},
//远程WMS服务器的类型, mapserver, geoserver or qgis
serverType: 'geoserver',
})
}),
];
var nyc = [-73.92722,40.774221];
var map = new ol.Map({
layers: layers,
target: 'map',
view: new ol.View({
center:ol.proj.fromLonLat(nyc),
zoom: 11
})
})
</script>
</body>
</html>

<!doctype html>
<html >
<head>
<link rel="stylesheet" href="css/ol.css" type="text/css">
<style>
.map {
height: 400px;
width: 100%;
}
</style>
<script src="lib/ol.js"></script>
<title>OpenLayers example</title>
<meta charset="UTF-8">
</head>
<body>
<h2>OGC WMS服务,方式二:ol.layer.Tile + ol.source.TileWMS</h2>
<div id="map" class="map"></div>
<script type="text/javascript">
var layers = [
new ol.layer.Tile({
source: new ol.source.OSM()
}),
new ol.layer.Tile({
source: new ol.source.TileWMS({
url: 'http://localhost:8080/geoserver/tiger/ows',
params: {
//WIDTH, HEIGHT, BBOX and CRS (SRS for WMS version < 1.3.0) 将被动态设置.
'LAYERS': 'tiger:tiger_roads',
'TILED': false,
'VERSION':'1.1.0',
'TRANSPARENT':true//
},
//远程WMS服务器的类型
serverType: 'geoserver',
// 用于渲染的不透明度过渡的持续时间。要禁用不透明过渡,设置transition为: 0
transition: 0,
projection:'EPSG:4326'
})
})
];
var nyc = [-73.92722,40.774221];
var map = new ol.Map({
layers: layers,
target: 'map',
view: new ol.View({
center:ol.proj.fromLonLat(nyc),
zoom: 11
})
})
</script>
</body>
</html>

根据请求参数可以知道,Tile
的请求方式是将地图当前范围按图块大小(width
*height
,默认为256*256)分割计算出多个bbox
,发送多个GetMap
请求获取地图图片。而ImageWMS
请求方式的参数中的宽高直接是地图当前视图的宽高,将当前地图视图范围作为bbox
边界,获取单张地图图片。
1.3 WFS服务
Web Feature Service (WFS)是OGC创建的标准,用于在互联网上使用HTTP,创建,修改和交换矢量格式的地理信息。支持对地理要素的插入、更新、删除、检索和发现服务,指定了发现操作、查询操作、锁定操作、事务操作和管理存储的、参数化查询表达式的操作。
服务可以根据HTTP客户请求返回GML(Geography Markup Language,地理标识语言)数据,也可以通过OGC Filter构造查询条件,并支持基于空间几何关系的查询和基于属性的查询以及基于空间关系和属性域的共同查询。
接口 | 操作类型 | 说明 |
---|---|---|
GetCapabilities | discovery | 获取该WFS服务支持的操作和服务的元数据文档 |
DescribeFeatureType | discovery | 获取WFS服务支持的功能类型的描述(图层属性字段等) |
GetPropertyValue | query | 根据要素属性值或部分属性值进行查询,返回符合表达式的要素 |
GetFeature | query | 从数据源中,获取指定图层符合条件的数据要素集 |
GetFeatureWithLock | query & locking | 返回并锁定指定图层的符合要求的要素,默认锁300s |
LockFeature | locking | 对指定的要素进行锁定,以保证一致性 |
Transaction | transaction | 对要素服务中的数据要素进行增删改的操作 |
CreateStoredQuery | stored query | 在服务端创建一个存储查询表达式 |
DropStoredQuery | stored query | 在服务端删除一个存储查询表达式 |
ListStoredQueries | stored query | 获取服务器上的存储查询变量列表 |
DescribeStoredQueries | stored query | 获取服务器上的每个存储查询表达式的详细元数据。 |
GetFeature操作
GetFeature操作返回的是选择的数据源信息和要素集。所以请求是针对特定的图层名称来执行GetFeature请求(namespace:featuretype)的。
参数 | 是否必须 | 说明 |
---|---|---|
version | 是 | 服务版本,默认1.1.0 |
service | 是 | WFS |
request=GetFeature | 是 | 请求接口 |
typename | 是 | 指定操作的图层名称(命名空间+图层名) |
outputformat | 输出的文本格式(GML2、GML3、JSON、CSV、JSONP、Shapefile) | |
bbox | 边界 | |
filter | 查询条件,xml文本(CQL/ECQL) | |
sortby | 排序,1.1.0及以上版本才有效 | |
maxfeatures | 返回要素集的最大记录数 | |
propertyname | ||
srsname | ||
faetureid | 要素id |
请求示例
http://localhost:8080/geoserver/wfs?request=GetFeature&version=1.1.0&typeName=topp:states&outputFormat=GML2&FILTER=%3CFilter%20xmlns=%22http://www.opengis.net/ogc%22%3E%3CFeatureId%20fid=%22states.23%22/%3E%3C/Filter%3E
请求流程: 当一个客户端想要访问WFS服务时,一般会涉及到以下的流程:
-
通过操作获取WFS服务支持的操作和要素类(FeatureType,可以理解为WFS中的数据集)
-
(可能)通过操作获取WFS服务支持的要素类的定义。
-
客户端发送某个操作的请求。
-
WFS服务处理请求。
-
WFS服务返回处理的结果和状态。
加载示例
在Openlayers中,加载WFS服务是在初始化矢量数据源ol.source.Vector
时,使用其url
或loader
参数的加载函数请求WFS服务的GetFeature
接口,在函数直接返回GetFeature
接口的要素集并给数据源设置要素集对应的解析器format或是在函数中解析要素集并添加到数据源中,最后使用ol.layer.Vector
渲染矢量要素。
<!doctype html>
<html >
<head>
<link rel="stylesheet" href="css/ol.css" type="text/css">
<style>
.map {
height: 400px;
width: 100%;
}
</style>
<script src="lib/ol.js"></script>
<title>OpenLayers example</title>
<meta charset="UTF-8">
</head>
<body>
<h2>OGC WFS服务:加载GeoServer的WFS服务</h2>
<div id="map" class="map"></div>
<script type="text/javascript">
var nyc = [-73.92722,40.774221];
var map = new ol.Map({
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
}),
new ol.layer.Vector({
source: new ol.source.Vector({
format: new ol.format.GeoJSON(),
url: function(extent) {
//直接返回WFS的GetFeature接口访问地址,设置outputFormat为json格式和format中的解析器一致
return 'http://localhost:8080/geoserver/wfs?service=WFS&' +
'version=1.1.0&request=GetFeature&typename=tiger:tiger_roads&' +
'outputFormat=application/json&srsname=EPSG:3857&' +
'bbox=' + extent.join(',') + ',EPSG:3857';
},
/*
* 加载策略,可选值:
* all,一次性加载所有的要素;
* bbox,加载地图当前视图范围内的要素;
* tile,基于瓦片格网加载要素
*/
strategy: ol.loadingstrategy.bbox
})
})
],
target: 'map',
view: new ol.View({
center:ol.proj.fromLonLat(nyc),
zoom: 11
})
})
</script>
</body>
</html>
<!doctype html>
<html >
<head>
<link rel="stylesheet" href="css/ol.css" type="text/css">
<style>
.map {
height: 400px;
width: 100%;
}
</style>
<script src="lib/ol.js"></script>
<title>OpenLayers example</title>
<meta charset="UTF-8">
</head>
<body>
<h2>OGC WFS服务:加载GeoServer的WFS服务</h2>
<div id="map" class="map"></div>
<script type="text/javascript">
var vectorSource = new ol.source.Vector({
format: new ol.format.GeoJSON(),
loader: function(extent, resolution, projection) {
var proj = projection.getCode();
var url = 'http://localhost:8080/geoserver/wfs?service=WFS&' +
'version=1.1.0&request=GetFeature&typename=tiger:tiger_roads&' +
'outputFormat=application/json&srsname='+proj+'&' +
'bbox=' + extent.join(',') + ',' +proj;
var xhr = new XMLHttpRequest();
xhr.open('GET', url);
var onError = function() {
vectorSource.removeLoadedExtent(extent);
}
xhr.onerror = onError;
xhr.onload = function() {
if (xhr.status == 200) {
//获取配置的解析器,解析要素集并添加到数据源中
vectorSource.addFeatures(
vectorSource.getFormat().readFeatures(xhr.responseText));
} else {
onError();
}
}
xhr.send();
},
strategy: ol.loadingstrategy.bbox
});
var nyc = [-73.92722,40.774221];
var map = new ol.Map({
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
}),
new ol.layer.Vector({
source: vectorSource
})
],
target: 'map',
view: new ol.View({
center:ol.proj.fromLonLat(nyc),
zoom: 11
})
})
</script>
</body>
</html>

在请求WFS服务时,可能会出现跨域问题。

解决方式可以在GeoServer中配置跨域支持。
将geoserver-2.18.1\lib中的jetty-servlets-9.4.12.v20180830.jar和jetty-util-9.4.12.v20180830.jar拷贝到geoserver-2.18.1\webapps\geoserver\WEB-INF\lib目录中,再修改geoserver-2.18.1\webapps\geoserver\WEB-INF目录下web.xml文件,将下列的注释取消,重启GeoServer。
<!-- Uncomment following filter to enable CORS in Jetty. Do not forget the second config block further down.
-->
<filter>
<filter-name>cross-origin</filter-name>
<filter-class>org.eclipse.jetty.servlets.CrossOriginFilter</filter-class>
<init-param>
<param-name>chainPreflight</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>allowedOrigins</param-name>
<param-value>*</param-value>
</init-param>
<init-param>
<param-name>allowedMethods</param-name>
<param-value>GET,POST,PUT,DELETE,HEAD,OPTIONS</param-value>
</init-param>
<init-param>
<param-name>allowedHeaders</param-name>
<param-value>*</param-value>
</init-param>
</filter>
<!-- Uncomment following filter to enable CORS-->
<filter-mapping>
<filter-name>cross-origin</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
参考文章
[1] WFS Reference :https://docs.geoserver.org/latest/en/user/services/wfs/reference.html
[2] Filter Reference :https://docs.geoserver.org/2.12.2/user/filter/filter_reference.html
[3] Filter Encoding :https://www.ogc.org/standards/filter
- 前端zip校验(添加rar格式)
- 后端重复上传校验
- 相关shp和项目(uuid)
- 根据机构编码拼接目录