当我们在浏览器输入一个地图网站时,实际上访问的是一个URL地址,比如请求一个地图瓦片的URL可能是 map.server.com/wms?service… ,这个URL不仅仅是一个网络地址,它还包含了按照特定规则组织的参数。这里的"特定规则"就是我们说的API接口,它定义了前端和后端如何交流。 就拿OGC的WMS服务来说,它规定了请求地图时必须包含哪些参数(如图层、范围、投影等),这些参数该如何书写,服务器又该如何解释这些参数并返回什么格式的数据。这就像制定了一种"通用语言",只要前端按照这种"语言规则"发送请求,支持OGC标准的地图服务器(如GeoServer)就能理解并正确响应。
而高德地图选择使用自己的API(比如"map.amap.com/tiles?x=204… 这些参数格式与OGC标准完全不同。这就是为什么高德必须开发自己的后端服务器,因为像GeoServer这样的标准OGC服务器无法理解高德特有的请求格式。
OGC——GIS专用API
WMS(Web Map Service)
- 前端请求
首先输入URL地址
GET /geoserver/wms?
SERVICE=WMS& 声明这是WMS服务
REQUEST=GetMap& 获取地图图片
LAYERS=rivers,roads& 需要显示的图层,如"rivers,roads"
STYLES=blue,black& 图层的渲染样式,如"blue,black"
BBOX=-180,-90,180,90& 地图范围,格式为"minX,minY,maxX,maxY"
WIDTH=800& 输出图片的像素高
HEIGHT=600 输出图片的像素宽
FORMAT=image/png/jpeg 输出格式可选
浏览器把URL地址封装为一个HTTP请求
GET /geoserver/wms?SERVICE=WMS&......(就是URL) Host: example.com User-Agent: Mozilla/5.0 ... Connection: keep-alive Accept: image/png/jpeg #返回img或png或jpeg ...
- 后端响应——PNG格式
--------------【图片数据的响应】---------------
89 50 4E 47 0D 0A 1A 0A // PNG文件头标识
00 00 00 0D // IHDR块长度
49 48 44 52 // "IHDR"标识
00 00 01 00 // 宽度(256像素)
00 00 01 00 // 高度(256像素)
08 // 位深度
06 // 颜色类型
[... 后续是图片数据 ...]
--------------------------------------------
WMTS(Web Map Tile Service)
GET /geoserver/gwc/service/wmts?
SERVICE=WMTS& # 声明这是WMTS服务
REQUEST=GetTile& # 请求操作类型:获取瓦片
VERSION=1.0.0& # WMTS服务版本号
LAYER=basemap& # 图层名称(瓦片服务图层)
STYLE=default& # 图层样式(通常为default)
TILEMATRIXSET=EPSG:3857& # 瓦片矩阵集(坐标系及瓦片规则)
TILEMATRIX=14& # 瓦片矩阵级别(缩放级别)
TILEROW=5287& # 瓦片行号(Y坐标)
TILECOL=1389& # 瓦片列号(X坐标)
FORMAT=image/png # 瓦片数据的格式(如PNG或JPEG)
WFS(Web Feature Service)
- 前端请求
GET /geoserver/wfs?
SERVICE=WFS& # 声明这是WFS服务
VERSION=2.0.0& # 版本号
REQUEST=GetFeature& # 获取要素数据
TYPENAME=rivers& # 要素图层名称
SRSNAME=EPSG:4326& # 空间参考系
BBOX=116,39,117,40& # 空间范围过滤(左下角和右上角经纬度)
MAXFEATURES=100& # 最大返回要素数
OUTPUTFORMAT=application/json/xml/gml # 输出格式可选
- 后端响应——JSON格式
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [ // 建筑物轮廓坐标
[116.3, 39.9], [116.31, 39.9], [116.31, 39.91], ... ]},
"properties": {
"建筑名称": "电视大厦",
"建筑高度": 100,
}
}
- 后端响应——XML格式
<gml:Feature>
<gml:geometry>
<gml:Polygon>
<gml:coordinates>116.3,39.9 116.31,39.9 ...</gml:coordinates>
</gml:Polygon>
</gml:geometry>
<gml:properties>
<建筑名称>电视大厦</建筑名称>
<建筑高度>100</建筑高度>
</gml:properties>
</gml:Feature>
WPS(Web Processing Service)
GET /geoserver/wps?
SERVICE=WPS& # 声明这是WPS服务
VERSION=1.0.0& # WPS服务协议版本号
REQUEST=Execute& # 请求操作类型:执行某个地理处理任务
IDENTIFIER=buffer& # 处理服务的标识符(例如缓冲区分析)
DATAINPUTS=geometry=POLYGON((116 39, 117 39, 117 40, 116 40, 116 39));distance=0.01& # 输入数据,包括几何和缓冲距离
RESPONSEDOCUMENT=true& # 请求返回文档格式的响应
OUTPUTFORMAT=application/json # 输出数据格式(如GeoJSON)
WCS(Web Coverage Service)
- 前端请求
GET /geoserver/wcs?
SERVICE=WCS& # 声明这是WCS服务
VERSION=2.0.1& # WCS服务的协议版本,常见值为2.0.1或1.1.2
REQUEST=GetCoverage& # 获取覆盖数据的请求
COVERAGEID=dem& # 要请求的栅格数据的标识符(图层名称)
SUBSET=Lat(39,40)& # 按纬度范围筛选(单位与坐标系一致)
SUBSET=Long(116,117)& # 按经度范围筛选(单位与坐标系一致)
RESOLUTION=0.001,0.001 # 数据的空间分辨率(经纬度单位)
FORMAT=image/tiff& # 输出数据的格式(GeoTIFF为常用格式)
- 后端响应——GeoTiff格式
一般摄影用的TIFF:主要存颜色,而遥感用的TIFF:存实际物理量和地理信息。 所以遥感的Tiff本身就有意义,并且还延伸了GeoTiff。GeoTIFF实际上是在TIFF规范基础上:定义了一套存储地理信息的标准,规定了如何保存地理参考信息,兼容TIFF的所有功能实际上。现在我们说的"普通TIFF"遥感影像,通常已经包含了这些地理信息,因为TIFF本身就支持多波段,支持不同数据类型(8bit、16bit等),可以存储元数据。日常你在GIS类软件里导出的遥感影像TIFF,其实都是GeoTIFF格式,只是没有特别强调"Geo"这个前缀。
// 普通TIFF的图像结构
Band 1: [数值数组] // 比如近红外波段
Band 2: [数值数组] // 比如红波段
Band 3: [数值数组] // 比如绿波段
// GeoTIFF在TIFF基础上增加了地理标签
GeoTags:
ModelTiepoints: [x,y,z, lon,lat,elevation] // 控制点
ModelPixelScale: [x-scale, y-scale, 0] // 像素分辨率
GeoKeyDirectory:
GTModelTypeGeoKey: 2 // 模型类型
GTRasterTypeGeoKey: 1 // 栅格类型
GTCitationGeoKey: "WGS84" // 坐标系统
GeographicTypeGeoKey: 4326 // EPSG代码
WMS与WCS服务的本质差异
这里写给那些没有遥感背景的GISer。
WMS (PNG/JPEG)就是普通图片的二进制数据,直接可以显示,但无法获取具体数值。WCS (GeoTIFF)是图片格式 + 地理信息,这个图片不是普通图片,因为每个像素的值是实际地理数值(如海拔),而不是单纯的RGB 0~255的颜色数值,因此可以用于空间分析。
普通照片和遥感影像虽然都能在屏幕上显示图像,但它们记录和使用数据的方式存在根本性的差异。普通照片中的RGB数值本质上就是用来表达色彩的,每个像素的红、绿、蓝三个数值直接对应显示器上的颜色强度,它们的意义仅限于视觉表达,这就决定了照片主要用于展示和艺术处理,比如调整亮度、添加滤镜或进行图像美化。
而遥感影像的波段数值则完全不同,它们记录的是地物的物理特性,可能是地物对不同波长光的反射率、地表温度的亮温值,甚至是雷达遥感中的散射强度。这些数值本身与色彩无关,只是为了便于人眼观察,我们可以通过软件将这些物理量映射到RGB色彩空间,呈现出"真彩色"或"假彩色"的效果。比如遥感影像里的森林是绿色,那是因为蓝波段反射率 0.1、绿波段反射率 0.3、红波段反射率 0.1,经过拉伸映射到 RGB 值为 (102, 204, 102),显示为绿色。普通照片里的森林,是因为直接记录RGB值为 (102, 204, 102),显示为绿色。
正是因为存储的是物理量,遥感影像可以用于各种专业分析,例如计算植被指数、估算地表温度或监测地物变化等。这种本质差异也导致了处理这两类数据时思维方式的不同。摄影师在处理照片时,会思考如何调整色彩来获得理想的视觉效果。而遥感专家在拿到一幅影像时,首先考虑的是这个影像包含了哪些波段数据,这些波段能够计算出什么指标,能够反映地物什么特征,完全是一种数据分析导向的思维方式,而不是着眼于视觉效果的艺术思维。可以说,遥感影像中的色彩显示只是其众多表达方式中的一种,而不是数据本身的核心价值所在。
OGC与RestFul的对比
HTTP 作为最基础的通信协议,定义了网络通信的基本规则,包括请求方法、URL格式、状态码、报文结构等内容,确保信息能够在网络上可靠地传输
- RESTful 是遵循 HTTP 协议的 API 设计理念,没有添加新的协议规则
- OGC 也是遵循HTTP协议的API设计产品,增加了特定的地理信息处理规则和特定的参数
在Web开发中,API设计风格直接影响到系统的灵活性、可扩展性和可维护性。OGC API和RESTful API是两种常见的API设计风格,它们在地理数据的传输和操作上有着显著的区别。首先,RESTful API的核心思想是将所有操作视为对资源URL的操作,通过HTTP标准方法进行这些操作。作为一种风格,不同开发者与不同的业务需求都可以设计多种不同的操作,下面例子我展示了 API 通用性设计的三个核心原则:参数化查询、资源抽象和减少冗余。
想象设计一个查询城市基础信息的 API。最初的设计是这样的:
GET /city/beijing/info
GET /city/shanghai/info
GET /city/guangzhou/info
这种设计看起来直观,但实际上是在为每个城市创建独立的端点。如果我们要支持全国所有的城市,这种方式会让代码极度臃肿。所以改进后的版本如下
GET /cities?name=beijing
通过参数化查询,我们用一个统一的端点替代了多个独立端点。这不仅让代码更简洁,还为我们提供了更大的灵活性。比如,我们可以轻松添加更多的查询参数
GET /cities?name=beijing&fields=population,area,elevation
GET /cities?province=hebei&min_population=1000000
但是真正的通用性设计还需要考虑资源的抽象。城市实际上是一种地理位置,那么可以这样设计
GET /locations?type=city&name=beijing
GET /locations?type=landmark&name=forbidden_city
GET /locations?latitude=39.9042&longitude=116.4074
现在我们的 API 不仅能处理城市,还能处理任何类型的地理位置。这就是资源抽象的威力:用一个通用的概念涵盖多种具体的应用场景。表面上看,一个通用的端点比多个专用端点要复杂。但实际上,它减少了代码的冗余。想象一下,如果我们需要为每种类型的地理位置都维护一个独立的端点,那才是真正的复杂。通过资源抽象,我们可以在一个地方统一处理所有的位置相关逻辑,无论是城市、地标还是具体坐标。所以我们最后的思路如下:
// 统一的位置处理逻辑
function handleLocationQuery(params) {
// 通用的参数验证
validateParams(params);
// 根据类型选择适当的数据处理方法
switch(params.type) {
case 'city':
return processCityData(params);
case 'landmark':
return processLandmarkData(params);
case 'coordinates':
return processCoordinates(params);
// 轻松扩展新的类型
}
}
OGC是规范
RestfulAPI是设计阶段的风格,OGC是已经设计完毕后的规范,换句话说,WMS就是WMS,就是说你只要调用WMS就得完完全全遵循它的规范,你也拓展不了功能,你也别想漏掉参数...以WMS为例,任何支持WMS的系统,都会遵循严格的参数约定。比如,SERVICE=WMS和REQUEST=GetMap必须在请求中明确指定,其他参数如图层、坐标参考系等也必须符合OGC标准。这种标准化的设计使得不同GIS系统(如GeoServer、QGIS Server、ArcGIS Server)之间能够无缝协作,保证了系统之间的互操作性。
OGC的资源与请求绑定
OGC服务与RESTful API的另一个显著区别在于资源定位的方式。在RESTful架构中,资源通过URL路径来定位,用不同的方法操作资源。而OGC服务中的资源和操作是紧密绑定的,通过固定的请求格式来完成。以WMS为例,GET /geoserver/wms?SERVICE=WMS&REQUEST=GetMap的请求中,操作(如GetMap)和资源(如图层roads)是同时定义的,不能随意分开。OGC服务并不像RESTful API那样注重资源和行为的解耦,它的请求和操作是高度绑定的。例如,WMS请求的GET /geoserver/wms?SERVICE=WMS&REQUEST=GetMap就是一个明确的操作请求,指定了获取地图图像的操作,而图层(如LAYERS=roads)和坐标系统(如SRS=EPSG:4326)等参数也都必须符合特定规范。
OGC的返回数据格式
同时,OGC服务通常使用XML等格式返回数据,而RESTful API则倾向于使用JSON格式。OGC服务的数据格式更适用于地理信息和地图数据的传输,能够处理复杂的空间数据结构。而RESTful API的灵活性和简洁性则更适用于一般数据的交换。
OGC+RestFulAPI配合
OGC的设计专注于地理数据的需求。GIS服务涉及到空间范围(如BBOX)、坐标系统(CRS)、图层样式(STYLES)等多个复杂的参数,这些参数之间有着复杂的依赖关系。OGC通过严格的参数结构和查询字符串的方式,能够有效地处理这些复杂的空间数据请求。这种设计方式比RESTful风格的路径参数更加清晰、易于理解,特别是在处理涉及空间分析和地图渲染的场景中。在一个WebGIS应用中,业务逻辑可以通过RESTful API进行处理,如查询项目资料、创建分析任务等;而地图数据的请求和分析则使用OGC风格的接口,这样的组合使用能够充分发挥两者的优势,使系统既具备灵活性,又能高效地处理复杂的地理数据。
API设计与落地阶段
当我们谈论API的“死板”与“灵活”时,实际上是在混淆了API设计阶段和使用阶段这两个阶段。以WMS为例,它要求请求中必须包含一些特定的参数,如bbox(边界框)、layers(图层)等,表面上看起来非常“死板”,但这种“死板”本质是其背后的业务逻辑,WMS服务需要这些特定的参数才能确定返回哪个地图区域,哪些图层的数据。它就像一个函数,必须接收特定的参数才能执行正确的计算,缺少任何参数都会导致无法生成正确的响应。实际上,这种“死板”是合乎逻辑的,并且是系统设计的核心需求。
同样,RESTful风格的API也并非没有“死板”的部分。比如,获取某个用户信息的接口 /api/users/{id},要求前端必须提供一个有效的用户ID才能返回该用户的信息。如果缺少id参数,后端就无法正确返回数据。在这个层面上,任何API在使用阶段都是“死板”的,因为前端必须严格按照接口设计的规定格式发送请求,后端才能处理并生成正确的响应。
真正的“灵活性”出现在API设计阶段。在这一阶段,开发者有能力自由定义API的路径、参数和响应格式。对于WMS服务,你完全可以修改GeoServer的源码,让它接收新的参数,或者做一些自定义的业务逻辑处理。同样,在设计RESTful API时,你也可以自由决定API的路径、允许的参数和返回格式。但一旦接口设计完成,前端就必须严格遵循这一设计,按照规定的格式来发起请求。这就是为什么我们称API的本质是一套“接口规范”:它规定了前后端之间如何进行可靠的通信。
因此,OGC API与RESTful API的根本区别不在于一个是“死板”而另一个是“灵活”,而在于它们各自的标准化程度和适用场景。OGC API(例如WMS)是一个被广泛采用的标准规范,旨在确保不同的GIS系统能够互相通信和互操作。相比之下,RESTful API通常是根据具体项目需求而定制的,具有更大的灵活性。
不过,值得注意的是,OGC API的设计哲学要求它保持标准化,确保不同GIS系统间的互操作性。因此,修改OGC服务(如GeoServer的WMS服务)来接收自定义参数并处理特殊业务逻辑,其实是不可取的。如果你修改了GeoServer,使其接受一个新的自定义参数并处理特定的业务逻辑,那么这个修改后的服务虽然基于WMS,但实际上已经不再是标准的WMS服务。其他遵循OGC标准的客户端(如QGIS、Leaflet等)将无法再与该服务兼容,这违背了OGC标准化的初衷——确保不同系统之间能够顺畅地交互。因此,更准确的做法是:如果你需要在OGC服务的基础上添加新的功能,应该开发一个独立的自定义API,而不是修改原有的OGC服务。这样可以确保OGC服务保持标准化,仍能与其他GIS系统互操作,同时通过自定义API来实现你所需要的特殊业务逻辑。这也是为什么许多商业地图服务商通常会选择完全自定义的API,而不是修改OGC标准的原因——他们需要更大的灵活性来实现自有的业务需求,而不受OGC标准的限制。