从零发布一个 WMS 服务:搞懂 GeoServer、Tomcat、Cesium 与 OGC 地图服务
(篇一)
最近在上杨帆老师的课程,接触并学习了 WebGIS 与 OGC 地图服务的相关内容。相比于单纯为了完成课程任务,我逐渐意识到,这门课所涉及的知识对我今后的学习和实践确实很有帮助。因此,我打算认真地把这门课学下去,真正理解其中的原理与应用,而不是囫囵吞枣、泛泛而谈。

本文主线:将本地 Shapefile 数据发布到 GeoServer,通过 WMS 对外提供服务,最后使用 Cesium 在三维地球中进行加载和显示。
其次,理解OGC、Web Service、WMS、REST等概念。
一、任务主线
先看最终的数据流:
Shapefile -> GeoServer -> WMS -> HTTP -> Cesium -> 浏览器中的三维地球
三个矢量数据:boundary.shp、buildings.shp、cun.shp 分别表示边界、建筑以及村界。
我们希望把它们发布成网络地图服务,最终让浏览器访问:http://127.0.0.1:8180/exp_geoserver_wms/
就可以在Cesium中看到这些图层。实验环境大致如下:
Windows 11
Tomcat 9.0.79
GeoServer 2.23.2
Cesium 1.88
Chrome
Tomcat使用8180端口。
二、为什么需要GeoServer?
首先要解决一个问题:浏览器能不能直接读取我的 .shp 文件然后显示?
当然可以通过各种前端库实现,但在真正的 WebGIS 系统中,通常不会简单地把原始空间数据文件直接扔给浏览器。
我们更希望有这样一个角色:客户端 -> “我要这一块地图” -> 服务器 -> 读取空间数据 -> 处理、渲染 -> 返回结果
这个“GIS 服务端”就可以由 GeoServer 来承担。
GeoServer 可以读取:Shapefile、PostGIS、GeoTIFF、空间数据库…,并且通过统一的标准对外提供:WMS、WFS、WCS、WMTS…,因此可以把GeoServer理解为:负责把本地或数据库中的空间数据包装成网络 GIS 服务的软件。
三、为什么需要Tomcat?
GeoServer 是 Java Web 应用,本次实验中以:geoserver.war的形式部署到 Tomcat 中。简单来说GeoServer运行在Tomcat提供的java运行环境中。
Tomcat本身并不知道:
- 什么是 Shapefile?
- 什么是 WMS?
- 什么是 EPSG:4326?
它主要负责:接收HTTP请求、找到对应Web应用(如GeoServer)、执行应用、返回HTTP响应。
而地图相关的工作交给GeoServer。

四、WMS服务发布流程
1、创建Workspace
进入 GeoServer 后台后,首先创建工作空间:ntu17。(给自己的地图服务划一个命名空间)
例如以后一个图层可能写成:ntu17:buildings,其中ntu17就是Workspace,这样不同项目之间即使存在同名图层,也不会发生混淆。
2、创建数据源Store
有了 Workspace,下一步就是告诉 GeoServer:我的空间数据在哪里?
这就是 Store。
本实验数据来自 Shapefile,因此创建 Shapefile 类型的数据源。
例如:
buildings.shp
发布之后,关系大致变成:
Workspace
↓
ntu17
↓
Store
↓
Shapefile
如果以后换成 PostGIS,Store 指向的就不再是 .shp 文件,而是数据库。
3、发布Layer
Store 只是告诉 GeoServer:
“这里有数据。”
还要进一步将数据发布成:
Layer
Layer 才是客户端真正能够访问的服务单元。
因此 GeoServer 中一个非常重要的关系是:
Workspace
↓
Store
↓
Layer
例如:
ntu17
↓
数据源
↓
buildings
发布完成后,客户端才能请求:
ntu17:buildings
4、配置Style
空间数据+SLD样式->地图
5、使用OpenLayers预览
发布图层后,可以使用 GeoServer 自带的 Layer Preview 进行预览。
这一部分很有意思。
表面上看:
点击 OpenLayers → 地图出现了。
但如果打开 Chrome:
F12 → Network
就会发现背后实际发生了网络请求。
其中最核心的就是:
GetMap
这就正式进入了 WMS。
五、WMS到底是什么?
WMS全称:Web Map Service,即Web地图服务。它是OGC制定的一种地图服务标准。
OGC解决的问题是:
客户端应该用什么方式向地图服务器请求地图?
如果没有标准:
ArcGIS 一种写法
GeoServer 一种写法
SuperMap 又一种写法
客户端开发会非常麻烦。
因此 OGC 制定规则:
大家都按照 WMS 的要求通信。
这也是 OGC 最重要的意义之一:
标准化+互操作
六、GetMap:真正获取地图
WMS 最核心的操作就是:
GetMap
客户端可能向 GeoServer 请求:
SERVICE=WMS
VERSION=1.1.1
REQUEST=GetMap
LAYERS=ntu17:buildings
SRS=EPSG:4326
BBOX=...
WIDTH=256
HEIGHT=256
FORMAT=image/png
TRANSPARENT=true
翻译成人话就是:
我现在使用 WMS 服务,请把 buildings 这个图层在指定空间范围内绘制成一张 256×256 的透明 PNG 图片给我。
其中:
LAYERS
指定需要哪些图层。
LAYERS=ntu17:buildings
BBOX
指定地图空间范围:
minx,miny,maxx,maxy
相当于告诉 GeoServer:
我要地球上的这一块。
WIDTH / HEIGHT
告诉服务器:
把这一块区域画成多大的图片。
例如:
256 × 256
FORMAT
指定返回格式:
image/png
因此整个过程可以总结成:
客户端
↓
GetMap
↓
GeoServer
↓
寻找图层
↓
读取 Shapefile
↓
应用 SLD
↓
按照 BBOX 渲染
↓
生成 PNG
↓
返回客户端
七、WMS另外两个核心操作
除了 GetMap,WMS 还有两个经常出现的操作。
1. GetCapabilities
可以理解成:
“你这里有什么?”
客户端请求 GetCapabilities 后,服务器会返回一份 XML 服务描述。
里面包括:
有哪些图层
支持哪些坐标系
支持哪些图片格式
支持哪个 WMS 版本
……
所以我更喜欢把它记成:
服务器的服务说明书。
2. GetFeatureInfo
可以理解成:
“我点的这里是什么?”
例如用户点击地图中的一个建筑:
鼠标
↓
┌──────┐
│建筑 │
└──────┘
服务器可以返回:
名称:教学楼
类型:建筑
高度:20m
因此三个操作可以直接记成:
GetCapabilities
你有什么?
GetMap
给我地图。
GetFeatureInfo
这里是什么?
八、Cesium如何调用WMS?
核心代码其实并不复杂:
var imageryProvider =
new Cesium.WebMapServiceImageryProvider({
url: "../geoserver/ntu17/wms",
layers: "ntu17:ntu17-group",
parameters: {
service: "WMS",
version: "1.1.1",
request: "GetMap",
format: "image/png",
transparent: true
}
});
然后:
viewer.imageryLayers.addImageryProvider(
imageryProvider
);
Cesium 就会开始向 GeoServer 请求地图。
九、整个请求过程
这是整个实验里我认为最值得理解的一部分。
最开始我们输入:
http://127.0.0.1:8180/exp_geoserver_wms/
第一步并不是直接访问 GeoServer。
而是:
浏览器
↓
HTTP GET
↓
Tomcat
↓
index.html
Tomcat 将:
index.html
返回浏览器。
浏览器开始解析:
<script src="...Cesium.js"></script>
发现:
我还需要 Cesium.js。
于是继续发 HTTP 请求。
随后执行 JavaScript。
当运行到:
new Cesium.WebMapServiceImageryProvider(...)
时,JavaScript 又向 GeoServer 发送新的 HTTP 请求。
所以完整过程应该是:
用户输入 URL
↓
浏览器
↓
GET index.html
↓
Tomcat
↓
返回 index.html
↓
浏览器解析 HTML
↓
加载 CSS / JavaScript / Cesium
↓
执行 JavaScript
↓
Cesium 构造 WMS 请求
↓
Tomcat
↓
GeoServer
↓
读取 Shapefile
↓
应用 SLD
↓
返回 PNG
↓
Cesium
↓
把图片贴到三维地球上
注意:
不是 index.html 被发送给 GeoServer。
而是:
浏览器解析 index.html 后执行其中的 JavaScript,由 JavaScript 再去请求GeoServer。
十、为什么 F12 里会看到很多 GetMap?

拖动、缩放地图时,会不断产生新的网络请求。
十一、为什么把前端和 GeoServer 都放进Tomcat WebApps?
本实验采用类似:
http://127.0.0.1:8180/exp_geoserver_wms/
http://127.0.0.1:8180/geoserver/
也就是说:
协议相同
主机相同
端口相同
这样属于:
同源
浏览器访问起来会简单很多。
否则例如:
前端:
http://localhost:8080
GeoServer:
http://localhost:8180
就可能涉及:
CORS
跨域
十二、WMS、WFS、WMTS、WCS

十三、Web Service
WMS 本质上也属于网络服务。
所谓 Web Service,可以简单理解为:
通过网络向其他程序提供功能或数据。
例如:
天气服务
地图服务
翻译服务
订单服务
地图只是其中一种。
早期 Web Service 中经常出现:
XML
SOAP
WSDL
可以简单理解为:
XML
= 数据怎么写
SOAP
= 消息怎么交换
WSDL
= 服务说明书
后来 Web 开发逐渐更多采用:
REST
+
HTTP
+
JSON
这样的方式。
十四、SOA、XML、SOAP、WSDL、RESTful。
1、SOA
Service-Oriented Architecture:面向服务的架构:把一个大系统拆成很多独立的服务,需要什么功能就调用什么服务。
2、Web Service
服务通过 Web 网络真正提供给别人调用。
3、XML
Extensible Markup Language:可扩展标记语言。
<Student>
<Name>张三</Name>
<Age>20</Age>
<Gender>男</Gender>
</Student>
一种结构化表达数据的格式。
4、XSD
XML Schema Definition
规定 XML 应该怎么写。
比如规定:
Student 必须有 Name
Age 必须是整数
Gender 可以是字符串
5、SOAP
Simple Object Access Protocol 简单对象访问协议
SOAP 是客户端和服务器之间交换结构化消息的一种协议。
而 SOAP 通常使用:
XML
来包装消息。
所以:
客户端
↓
SOAP消息
↓
服务器
SOAP 消息里面常常就是 XML。
十五、WMS 流程中的 XML 与 KVP 请求
1. GetCapabilities 返回的是 XML
如果你请求:
SERVICE=WMS
REQUEST=GetCapabilities
GeoServer 返回的服务说明书通常就是 XML,比如描述:
有哪些图层
支持哪些坐标系
支持哪些格式
所以这里明确涉及 XML。
2. 你用的 SLD,本身就是 XML 格式
你实验里配置过 GeoServer 的 Style / SLD。
SLD 全称 Styled Layer Descriptor,其内容本质上就是 XML,例如类似:
<StyledLayerDescriptor>
...
<PolygonSymbolizer>
...
</PolygonSymbolizer>
</StyledLayerDescriptor>
所以你其实已经用到 XML 了,只是 GeoServer 图形界面帮你屏蔽了很多细节。
3. 但你的 GetMap 请求本身不一定是 XML
你目前 Cesium 发的 WMS 请求主要是这种:
?SERVICE=WMS
&REQUEST=GetMap
&LAYERS=...
&BBOX=...
&FORMAT=image/png
这种叫 KVP(Key-Value Pair,键值对)请求,就是 URL 后面一串参数。
然后 GeoServer 返回:
PNG
所以这一段是:
HTTP + KVP
↓
WMS GetMap
↓
PNG
而不是:
XML → XML
十六、从传统OGC到OGC API
传统 OGC 服务的请求经常长这样:
SERVICE=WFS
REQUEST=GetFeature
TYPENAME=buildings
也就是说:
调用某一个操作。
现代 OGC API 开始越来越靠近普通 Web API。
例如可能采用类似:
GET /collections/buildings/items
这时:
buildings
直接被看作一个资源。
返回数据也更多使用:
JSON / GeoJSON
因此可以粗略理解为:
传统 OGC:
HTTP
+
SERVICE
+
REQUEST=GetXXX
+
XML/GML
逐渐发展为:
OGC API:
REST风格
+
HTTP
+
JSON
这让 WebGIS 与现代 Web 开发的技术体系越来越接近。