发布日期 : 2018-01-19 01:12:20 UTC
访问量: 2125 次浏览
一、缘起
一直在使用GeoServer,从来没关心它的实现。也是GeoServer
设计的实在太好,下载,安装,启动页面,根本不费力。这是其一,
其二,GeoServer遵循OpenGIS的开放标准WMS,WFS,WCS,这3个
标准涵盖了大部分WebGIS基础应用,一般情况下不太需要在服务端
做什么开发了。
那么会不会有不一般的情况呢?如果直接用GeoServer实现业务级别的
REST服务是不是会更高效呢?如果搞清楚它的结构遇到奇怪问题时
是不是就不必到处求人了呢?如果,也许只是如果,有一天你自己
不得不实现一个服务器,今天的学习是不是会有所帮助呢?除去以上
原因,难道你就不想知道它是怎么工作的吗?好了,不再废话了,
让我们赶快开始吧。
二、预备
1)下载源码,我使用的是最新稳定版2.0.2;
2)下载工具,JDK,Eclipse,Maven,SVN,这些东西可以去官网下载;
3)跟着说明,产生Eclipse项目(这个过程比较耗时);
4)打开项目,会看见下面这些包(其实还有很多插件之类的包,我都删除了)

5)可以从Eclipse启动GeoServer了。

如果你已经安装了GeoServer,现在也可以打开它的登陆页面进行操作。
三、结构
在深入代码之前,先来熟悉一下代码的结构。所有“web”打头的
包暂时可以不关心,注意力集中在“platform”,“main”,“ows”,
“wfs”,“wcs”,“wms”这6个包上。我简单介绍下它们的关系,下图

展现了包之间的依赖关系,下面的包依赖上面的包,最顶端是“platform”。
“platform”,“ows”和“main”(这3个完全可以合在一起嘛)
包含了GeoServer最基础最核心的类和接口,下面介绍一些重要的
类和接口,“wfs”,“wcs”,“wms”将利用这些类来完成具体的功能:
1)platform包的org.geoserver.platform.Service类代表一个具体的
服务,例如WMS,它用ID和VERSION来唯一标定,每一个服务都会提供
若干操作(Operation);
2)platform包的org.geoserver.platform.Operation类代表某个服务
下可以被请求的操作,例如GetCapabilities,这个类利用Java的反射机制;
3)ows包的org.geoserver.ows.Dispatcher类处理所有OWS的请求,
这个类将是我们调试的重点;
4)main包的org.geoserver.catalog.Catalog接口包含资源访问的
方法,这些资源有“Layer”,“Layer Group”,“Map”,
“Namesapce”,“Resource”,“Store”,“Style”和“Workspace”,
我们会在后面对这些资源做详细的讲解,了解了它们就知道GeoServer
是如何组织和使用数据的了;
5)main包的org.geoserver.config.GeoServer接口包含访问服务器
公共配置信息的方法,我们将会在很多场合看到它;
6)main包里面还有一些描述资源的接口,例如
org.geoserver.catalog.LayerInfo代表“Layer”资源,这些接口
我们也会在后面的章节逐一介绍。
四、第三方库
GeoServer使用了近百个第三方软件包(丰富第三方软件包也许是Java
最迷人也最迷惑人的地方)。下面我会介绍一些我认为比较重要或
者比较有趣的:
1)GeoTools可以说是Java语言的GIS标准包,它继承了GeoAPI,
一个符合OGC简单要素访问协议(Simple Feature Access)的Java包,
提供了大量GIS操作,包括多种格式的空间数据源访问,地图渲染,
空间几何操作,GeoServer的GIS部分完全使用它来实现;
2)SpringFramework是一个程序框架(wiki的解释),GeoServer
用它来构建运行时环境,我们会在“main”,“wcs”,“wfs”和
“wms”下面看到这样一个文件“applicationContext.xml”,
这个文件告诉spring框架需要创建哪些类实例,以及如何创建。
下面来看个典型配置:

这是“main”的配置文件的一部分,它构建一个基本的运行环境;
3)FreeMarker是一个模板引擎(官网的定义),用它提供的模板语言,
我们可以很容易实现对象模型与输出格式的分离,GeoServer用它来
实现某些HTML文本的输出(我觉得GeoServer对FreeMarker的使用
还不够充分,我会把所有的文本输出全部交给它来完成)。
五、预演
本文的最后让我们来看看我们将如何深入GeoServer的代码。方法很简单,
就是下断点然后跟踪调试。我们知道WMS里面最基本的方法是GetCapabilities,
因此我们在wms包里寻找与“GetCapabilities”相关的内容,很快就发现了类
org.vfny.geoserver.wms.responses.WMSCapabilitiesResponse,
姑且先不管它是什么反正和GetCapabilities有关,在继续查看了它的
代码后,确认“execute”函数是关键。我们启动程序,然后在execute
里面下断点,如下图:

现在我们在浏览器里敲入这个地址
“http://localhost:8080/geoserver/wms?request=getCapabilities”,
回车。程序停留在断点处,这时我们重点来看调用栈,如下图:

我们发现,原来调用是Dispatcher的response方法传递来的。打开
Dsipatcher类的代码仔细查看,很快(其实花了我半天的时间)理清了
它处理请求的过程,用伪代码描述如下:
//解析HTTP请求,创建请求参数
var request = parseRequestParams(requestURL);
//通过SERVICE和VERSION来寻找合适的服务对象
var service = findService(request.SERVICE,request.VERSION);
//创建执行对象
var operation = buildOperation(service,request.REQUEST,request.PARAMS);
//执行操作,返回结果
var result = execute(operation);
//将结果写入返回流
response(result,request,operation);
到此我们可以确定Dispatcher类是处理请求的核心,一切就从这里开始。
最近几年来,地理信息系统无论是在理论上还是应用上都处在一个飞速发展的阶段。 GIS被应用于多个领域的建模和决策支持,如城市管理、区划、环境整治等等,地理信息成为信息时代重要的组成部分之一; “数字地球”概念的提出,更进一步推动了作为其技术支撑的GIS的发展。 与此同时,一些学者致力于相关的理论研究,如空间感知、空间数据误差、空间关系的形式化等等。 这恰好说明了地理信息系统作为应用技术和学科的两个方面,并且这两个方面构成了相互促进的发展过程。