1. 前言
WebGIS是Internet技术应用于GIS开发的产物。WebGIS,即互联网地理信息系统,以互联网为环境,以Web页面作为GIS软件的用户界面,把Internet和GIS技术结合在一起,为各种地理信息应用提供GIS功能。GIS通过Web功能得以扩展,通过Web发布地图、浏览空间数据,制作专题图,例如大家熟悉的Go2Map、Google Map、MapBar等等。
随着GIS应用的不断加深和广泛,WebGIS逐渐成为很多GIS工程的首选方案,那么什么是WebGIS,WebGIS的内部机制和架构是什么,WebGIS平台的关键技术等问题也成了很多开发人员关注的问题。也许绝大多数人不会去实现WebGIS平台,但一项技术“知其然”和“知其所以然”还是有所差别的,因此我们使用.net Remoting和SuperMap Object设计了一个简单的WebGIS系统,从纵剖面的角度来剖析其WebGIS的内部结构。本文所涉及到的知识有:组件GIS开发、.net Remoting、ASP.net开发和控件开发、设计模式。
2. WebGIS的基本原理
WebGIS的原理并不复杂,主要流程如图 1所示:
(1)首先,设计一个可以交互的Web页(可以应用ASP、PHP、ASP.net、JSP等,商用WebGIS大多选择除了PHP的其他语言,而开源WebGIS大都选择了PHP),通过此Web页,向Web服务器提交有关GIS服务的请求;
(2)此请求会包含对地图数据的请求,包括查询等,请求会通过Web服务器提交给GIS应用服务器;
(3)GIS应用服务器可以使用几种技术,CGI、COM、Java Serverlet或者.net技术、Web Service技术,通过这些组件包装已有的GIS软件,获取客户端的请求,将用户需求转化为具体的操作,返回需求的数据(一般是一个地图图片或者查询的数据集),这个过程称为地图的Render,实际上也是最为耗时的操作;
(4)Web服务器获取了GIS应用服务器返回的图片,然后作为一个Web页返回给客户。
图 1 WebGIS的基本架构
这就是WebGIS的基本原理,另外一类基于客户端插件,如ActiveX或者Applet的WebGIS系统,差别在于GIS服务器不生成图片,而返回矢量数据集。这样,可以看出,WebGIS的关键是设计GIS应用服务器,该服务器的性能和效率很大程度上决定了WebGIS的性能。
3. WebGIS的设计
接着我们来设计一个自己的WebGIS系统。我们的需求非常简单,可以将一个地图以固定的分辨率显示在Web浏览器,可以放大、缩小和移动。这个功能虽然简单但五脏俱全,大概可以一窥WebGIS的基本原理。
我们选择使用.net技术,首先需要对系统进行划分,Web开发使用ASP.net的Web Control来封装一个简单的控件,ASP.net的Web页通过此控件来显示地图,控件包括几个主要操作的接口。此Control每次Render的时候都需要调用GIS服务器获取需要的数据,然后将此图片Render为Web页的一部分。
GIS服务器负责打开GIS空间数据,接受请求,生成图片,然后返回之。我们知道,空间数据的打开、关闭是非常耗时的操作,因此,GIS服务器应该保证“一直开着”,而不是一个简单的组件,每次请求时都打开、关闭GIS数据。要获得这样的功能可以通过几种方式:(1)使用一般控件或Web Service,在Global.asax中的 Application_Start 中启动打开数据;(2)使用Windows服务;(3)使用Remoting技术,通过启动服务的方式来启动GIS服务器实例,采用Singleton方式调用服务器端,然后引用此服务器实例,同时可以在此保存请求状态,进行缓存处理。实际系统大概是同时使用了几种技术,例如使用Windows服务在开机时启动,然后创建Remoting服务器端。
一般来说,GIS服务器都使用了创建Map Service(地图服务)的方式,就是说,可以在GIS服务器创建多个Service,提供Map服务。这样,前端的Web页调用Map Service服务,服务控制空间数据,在Web程序调用之前,GIS服务器已经打开了空间数据,等待提供服务。这样,我们一方面对程序进行了分层,另一方面通过分层,意外的获得了可以通过在GIS服务器端控制Map Service的方式更新、修改地图数据,而不影响Web服务的好处。
图 2即为一个基于.net设计的WebGIS的架构示意,不同颜色表示可以部署于不同的机器。其中GIS应用服务器上运行Map Service,为前端的Web程序提供地图数据。
图 2 基于.net Remoting和ASP.net的WebGIS设计架构
4. 详细设计与系统实现
4.1. GIS服务器(基于.net Remoting)
在运行于不同进程中的对象之间建立通信(无论是在同一台计算机上,还是在相距数千公里的计算机上)是常见的开发目标。通过 .NET 远程处理,客户端应用程序可以使用同一台计算机(或其网络中其他任何可用的计算机)上的其他进程中的对象。可以从 Web 应用程序、控制台应用程序、Windows 服务进行通信。因此我们将基于.net Remoting技术实现GIS服务器。
MapRender接口
我们首先设计如下的一个MapRender接口(图 3),在服务器端实现之,客户端则通过Remoting远程调用,使用Server端的服务。
图 3 MapRender接口
MapService类
图 4 MapService类
MapService实现了MapRender接口,提供Map服务,返回生成的Map的文件名(图 4)。其实现是通过委托模式,调用 _mapEngine (MapEngine的实例)来完成具体的操作。
MapEngine(具体的地图引擎)
MapEngine是地图引擎的实现的基类,然后在此基础上继承不同的引擎(图 5)。对于使用MO和SuperMap的引擎,可以使用Adapter模式来实现。Simple引擎只是返回一个已有的图片地址,用作测试。
图 5 地图引擎设计
地图引擎首先实现了一个基类,然后在此基础上继承不同的引擎。对于使用MO和SuperMap的引擎,可以使用Adapter模式来实现。Simple引擎只是返回一个已有的图片地址,用作测试。
实际的程序可以从配置文件里读入需要的数据,然后通过工厂方法初始化MapEngine。
Private Shared Function MapEngineFactory() As MapEngine
Dim strMapEngine As String
Dim mapEngine As MapEngine
strMapEngine = "Supermap"
Select Case strMapEngine
Case "Simple"
mapEngine = New SimpleMapEngine
Case "Mo"
mapEngine = New MoMapEngine
Case "Supermap"
mapEngine = New SupermapMapEngine
Case Else
mapEngine = New SimpleMapEngine
End Select
Return mapEngine
End Function
MapServer类和启动Map Service服务
Main函数设计在MapServer类中,其中的MapEngine被设计为Singleton(单件)对象,已保证只有一个具体的MapEngine引擎,通过MapEngineFactory的工厂方法返回具体的对象,然后在Main函数内启动MapService服务:
Dim chan1 As TcpChannel
chan1 = New TcpChannel(8085)
ChannelServices.RegisterChannel(chan1)
RemotingConfiguration.RegisterWellKnownServiceType(GetType(MapService), "MapService", WellKnownObjectMode.Singleton)
MapEngine = MapEngineFactory()
MapEngine.run("")
System.Console.WriteLine("Hit <enter> to exit...")
System.Console.ReadLine()
Application.Exit()
将MapService定义为可远程调用,而在MapService中调用实际的MapEngine,来完成请求。
例子中将所有实现写在了代码中,实际的实现,可以使用类似代码和配置文件,启动多个Map Service服务,供不同的地图程序调用。
测试Map Service服务
我们可以创建一个WinForm程序来测试此Map Service服务,首先,添加MapRender接口IMapRender的引用,对在Form Load事件里初始化远程对象MapService:
Dim chan As TcpChannel
chan = New TcpChannel
ChannelServices.RegisterChannel(chan)
_map = CType(Activator.GetObject(GetType(IMapRender.MarsWebGIS.IMapRender), "tcp://localhost:8085/MapService"), IMapRender.MarsWebGIS.IMapRender)
这样,我们就可以使用 _map 对象获取Map Service服务,返回需要的数据。
Dim strFileName As String
Dim img As Bitmap
Dim l, t, r, b As Double
l = CDbl(500000 * Rnd() - 2000000)
t = CDbl(500000 * Rnd() - 2000000)
r = CDbl(l + Rnd() * 10000000)
b = CDbl(t + Rnd() * 10000000)
strFileName = _path & _map.GetMap(t, l, r, b, _path)
Me.lblImg.Text = strFileName
img = New Bitmap(strFileName)
Me.picMap.Image = CType(img, Image)
运行结果如图 6所示:
图 6 GIS服务器测试运行
下面,我们就可以在使用ASP.net创建使用此远程服务的控件,在Web上使用GIS地图服务,实现WebGIS。
4.2. Map Control的创建和测试
现在,我们已经可以在ASP.net开发中直接使用上面实现的Map Service,我们可以通过控制GetMap的参数,来实现移动、大小缩放等基本功能。
为了文章的完整性,我们来封装一个简单的Map Control控件。
图 7 MapControl类
该控件在New事件内初始化 _map 调用远程的Remoting服务(Map Service),和前面的测试一样,可以使用如下方法初始化:
_map = CType(Activator.GetObject(GetType(IMapRender.MarsWebGIS.IMapRender), "tcp://localhost:8085/MapService"), IMapRender.MarsWebGIS.IMapRender)
然后在Render事件内调用GetMap。我们可以在此控件内通过GetMap参数封装移动、大小缩放等基本功能。
下面我们测试一下此控件。新建一个ASP.net页,增加以下引用:
<%@ Register Assembly="MapControlLibrary" Namespace="MapControlLibrary" TagPrefix="MapControlLibrary" %>
然后就可以使用控件:
<MapControlLibrary:MapControl id="Map1" runat="server">
</MapControlLibrary:MapControl>
运行结果如图 8所示:
图 8 IE中的运行结果示意
这样,我们就完成了一个简单的WebGIS框架。
5. 总结
该框架可以算作WebGIS的一个简单的纵剖面,由此我们可以明白WebGIS系统的架构,需要的技术,框架设计和设计模式的应用。
由于笔者对于Remoting和ASP.net控件技术不太熟悉,文中难免有所疏漏,存在不少错误和问题,还欢迎大家一起讨论。最后希望所有做GIS的同行可以更多关注架构和模式,提高我们的设计能力。
本文的开发测试环境为:
Windows XP
Microsoft Visual Studio 2005 Beta 2
SuperMap Object 3.2
备注:本文引用自http://www.cnblogs.com/maweifeng/articles/250284.html