浅析ArcIMS
引言
最早使用的ArcIMS是3.5还是4.0忘记了,很久前的事情了。当时是做一个简单的系统,包括地图的 显示,点击显示一个点对象的属性信息,对这些属性的查询,以及添加点对象到一个图层。显示和界面的东西都不需要编程实现,使用ArcIMS的Author 和Design就可以了,然后简单调整一下布局和颜色,由于是内部使用,这部分无所谓。而添加点对象到某个图层,就需要使用其他方法了,当时的做法是使用 MO封装了一个ActiveX EXE(MO无法封装为ActiveX DLL),然后通过ASP调用。这次重拾ArcIMS,安装、试用,第一感觉是很熟悉,毕竟这么多版本以来,ArcIMS变化不大,或者说,没有什么变化。第二是ArcIMS速度挺快,这2年也用过MapXtreme、MapServer,一直以为ArcIMS慢,这次安装后发现其实挺快。因为没有测试数据,一台计算机也不好做测试,不过感觉上,ArcIMS占上风,这也许和其实现有关,后面再说。
几个要点:
- ArcIMS的定位是空间数据发布系统,虽然也可以做进一步定制和开发,但因为ArcIMS的定位,有些事情很难或无法实现,例如无法(很难)使用ArcIMS进行复杂的空间分析(嗯,可以调用AO或者MO,这个另当别论)。
- ArcIMS和目前的ArcGIS Server不是一个基础,后者基于由COM实现的AO,不过由于ArcIMS任务单一,所以效率较高,而且可以跨平台(核心代码应该是ArcInfo时代的纯C++?)。
- Web服务器的Application Server Connector和ArcIMS的应用服务器(Application Server)的通信是基于Servlet发送ArcXML,因此需要安装Java环境和Servlet运行环境。ArcIMS的Author和Design、Administrator也是基于Java实现。
- ArcIMS的几个主要部件:
- Application Server Connectors,即ArcIMS定制开发的API,有Java、ActiveX、.net等API,但最终和Application Server通信,都需要将请求转换为ArcXML,由Servlet Connector发送给Application Server,这也是为什么ArcIMS需要一个Servlet运行环境的原因;
- Application Server,应该是基于Java实现,主要用于维护Spatial Server的状态及其与Web服务器的交互。
- Spatial Server,核心的地图渲染器,基于C++实现?主要用于根据请求渲染地图,即地图render。
- ArcIMS的开发模式:
- 使用Author、Designer通过可视化方式来设计地图,发布,无须编程;
- 使用Connectors来开发,目前可以使用ASP、.net、Java等等方式来开发。
- 闲话,记得有过ArcView IMS,MO IMS的产品,没有使用过,应该是类似MapXtreme for Windows的产品,这个东东是基于MapX实现的,而MapXtreme.net和MapXtreme for Java则是比较纯粹的产品。
- ArcIMS的核心是ArcXML,ArcXML是Web服务器的Application Server Connector,Application Server,Spatial Server之间的通讯协议(语言),其调用模式类似Web Service。
ArcIMS的架构
ArcIMS的体系结构如下图所示:这个结构应该是在ArcIMS 3.0的时候就确定下来的,之后基本没有什么变化。ArcIMS 3.0的发布时间是2000年,而2000年正是3-tier架构开始成为主流的年代。
每 层具体的说明可以查看ArcIMS的文档,早先的文档和资料一般把客户端归于表现层,Web Server、Application Server、Spatial Server归于逻辑层,空间数据归于数据层。其实与这些层次做一一对应也无大的必要。其中的Web Server及Application Server Connectors可以部署在一台计算机;Application Server可以部署在一台计算机;而Spatial Server可以部署于多台计算机,由Application Server管理;数据则可以是文件,SDE等格式。实际中,一般把Spatial Server安装于多台计算机,因为Spatial Server是整个系统中负荷最重的部分,执行了大部分的运算任务。
Application Server管理Spatial Server,处理ArcXML请求,并返回ArcXML的结果,对于不同的开发接口(Connector),或者也处理这样的XML,或者由 Connector封装了此类请求,然后在后台与Application Server交互。
运行于Application Server的地图服务(Service)是无状态的,也就是说他只是根据ArcXML请求,调度Spatial Server来不断的生成图片或者其他数据,然后以ArcXML的格式返回给Web Server的Application Server Connectors。因此,用户(地图)的状态,例如当前的缩放比例,位置等,或者在Web服务器端通过Seesion保留,或者在客户端通过某种方式 保留(如表单的隐藏域,Url参数等等)。
对于WebGIS的架构和实现,可以参照笔者以前写过的几篇文章,应该对理解ArcIMS的架构有用处:
WebGIS系统的设计与实现
http://maweifeng.cnblogs.com/articles/210080.html
使用.net Remoting和SuperMap Object设计WebGIS系统
http://maweifeng.cnblogs.com/articles/250284.html
开发模式与运行机制
使 用ArcIMS的设计工具Author、Designer来编辑Axl定义文件,增加地图服务,定制Html客户端或者Java客户端,发布地图服务,这 种开发模式都属于客户端处理模式;而使用ActiveX Connector,.Net Link的方式开发,则属于服务器端处理模式。这里的处理是指处理ArcXML。客户端处理模式,使用Html客户端或者定制Html客户端开发。系统的运行机制如下:
这种模式下,客户端的请求已经是ArcXML格式封装的,然后由Web服务器委托Application Server Connectors处理,由于请求已经是ArcXML格式,Connector的任务只是简单的把请求转发给Application Server。
这种模式下,发送和返回请求都需要在客户端来处理,因此,ArcIMS的Html客户端的JS代码行数达到万行级别,也就不奇怪了。另外,返回和发送ArcXML,其中很多数据都是无关紧要或者不需要的,对于网络通信,也是一个负担。
得到服务器端返回的ArcXML后,客户端JS负责解析,然后再在服务器下载需要的图片,显示在客户端。
相 关的代码在HtmlViewer的Javascript代码的aimsMap.js这个文件内,一般的地图操作设置参数后调用sendMapXML函数, 然后此函数再调用sendToServer函数,最后由htmlSendToServer通过表单方式发送请求(没有使用XMLHttpRequest对 象,所有XML操作都是由JS完成)。ArcIMS文档中的“Customizing_the_HTML_Viewer.pdf”中对 HtmlViewer的结构、运行原理、定制有详细的说明,可以作为参考。
对于ArcExplorer,JavaViewer等都是使用客户端处理模式。
服务器端处理模式,包括使用Java、ASP、.net等开发的方式来定制开发的ArcIMS应用。其运行机制如下:
对 于服务器处理模式,ArcXML的转换、解析在服务器端由Application Server Connector进行。客户端的代码由服务器端的ASP、JSP等程序动态生成。客户端发送地图服务请求后,由服务器端的API转换为ArcXML,然 后由Servlet发送给Application Server。
与客户端处理模式比较,服务器端处理模式的优势有:更少的数据传输,更易与其他程序集成等。
采用服务器处理模式开发,客户端还是需要处理用户操作,例如放大缩小,要获得好的用户交互体验,这部分还是需要较强的JS才可以完成,好在ArcIMS的例子中提供的JS代码已基本够用。
下面将分别以ActiveX Connector和.net Link为例来分析ArcIMS的开发。
使用.net Link
.net Link是使用.net Framework来开发ArcIMS应用程序的API。使用.net Link的步骤为:1. 增加.NET Link的程序集引用到项目,程序集位于目录:
<ArcIMS Installation Directory>\ArcIMS\Connectors\NET_Link
2. 连接到Application Server,可以使用HTTP或者TCP连接,例如下面的代码建立一个TCP连接:
using ESRI.ArcIMS.Server; .. ServerConnection connection= new ServerConnection(); connection.Host="localhost"; connection.AppServerPort=5300; connection.Scheme=Scheme.TCP; |
3. 发送一个ArcXML request。
4. 处理返回的ArcXML response。
和HTML下的JS相比,.net Link只是把XML操作使用.net程序集封装了,并不是一个很面向对象的封装,还需要开发者处理“机器友好,人类不友好”的XML。这也是笔者对.net Link比较失望的原因。
下面来看看随ArcIMS一起安装的.net Link的例子“BlueViewer”。工程的设置,数据安装,ArcIMS的设置请参考例子目录下的readme.htm。
设置好以后就可以在浏览器中打开这个站点,是一个包括了放大缩小等简单功能的地图服务,如下图所示:
用VS 2003打开工程,其解决方案如下图所示:
其中的核心是js代码和MakeMap.aspx这个文件,我们来做一个分析。
程 序的default.aspx中除了界面元素,定义了hvMinX、hvMinY、hvMaxX、hvMaxY、hvMapPage,为 HtmlControls.HtmlInputHidden类型(表单的隐藏域),前4个对象的值指示当前地图的范围,最后一个则用来获取地图的url。
在Page_Load过程中,有如下的语句:
hvMapPage.Value = "MakeMap.aspx" |
也 就是说,hvMapPage对象的值最终由MakeMap.aspx来返回。我们先看看MakeMap.aspx这个文件。这个文件的逻辑很简单,在 Page_Load过程中根据地图范围发送一个ArcXML请求,并获得Response,解析这个XML,最终如果成功,则定向到生成的图片文件 url,或者返回错误信息:
If bRequestFailed Then ... Else Response.Redirect(imageURL) End If |
这样,通过重定向,最终由ArcIMS生成的图片的地址被赋值给default.aspx中hvMapPage的值,我们再回到default.aspx,看这个图片最终是如何显示出来的。
在default.aspx中,在页面的load事件中调用了js函数startUp():
<BODY onload="startUp()" MS_POSITIONING="GridLayout" style="MARGIN: 0px"> |
startUp()定义在main.js中。在startUp()中通过一系列的初始化,然后显示Loading图片(加载地图的那段动画),并指定事件:
m_imgMapCanvas.onload = hideWaitImage; |
即当m_imgMapCanvas(最终显示的地图的图片)显示以后,调用hideWaitImage过程,隐藏Loading图片(NC需要特殊处理)。
最 后调用submit函数。submit函数根据目前的地图范围,发送一个submit,这时候,服务器端MakeMap.aspx就会运行,最后把结果 (图片的url)保存在hvMapPage的值中。我们在default.aspx中也看到,MakeMap.aspx也必须是提交表单后才运行,就是这 个道理。
请求(submit)返回后,替换显示图片的url:
m_imgMapCanvas.src = sURL; |
而m_imgMapCanvas就是default.aspx中中间显示地图的区域,为一个<img>。
对于NC需要特殊处理以隐藏Loading图片,对于IE则自动调用hideWaitImage函数来隐藏之。最后调用persistExtent函数把地图范围保存在hvMinX等几个隐藏的表单域中。
这样,我们就对这个例子的运行机制和过程做了一个纵向的剖析,从中我们也看到,.net或者ASP.net的工作其实很少,仅仅是发送和解析ArcXML请求,地图的显示和操作都集中在JS代码中。
使用ActiveX Connector来开发
ActiveX Connector应该是ArcIMS里比较成熟的一个API,另外的应该是Java的API。ArcIMS的例子在Samples的ActiveX目录下,ActiveX_Samples是使用ASP来操作ArcIMS的一些例子,例如获得一幅地图:
Set mConnector = Server.CreateObject("aims.ArcIMSConnector") mConnector.ServerName = "localhost" mConnector.ServerPort = 5300 Set mMap = Server.CreateObject("aims.Map") resultInit = mMap.InitMap( mConnector, "SanFrancisco" ) mMap.Width = 500 mMap.Height = 300 mMap.BackColor = 15130848 urlImage = mMap.GetImageAsUrl() Response.write "<IMG SRC=" + urlImage + ">" |
创建aims.ArcIMSConnector对象,与Application Server的连接,创建Map对象,并与一个Service绑定,然后设置大小,调用GetImageAsUrl返回一个图片的Url。
ActiveX_Template目录下有图层、地图、选择操作等一些模版,可以在自己的程序中使用。大多程序都通过Session来保存地图对象,然后通过该对象来运行。
和.net Link比较,ActiveX Connector是一个比较成熟的API,但由于ASP本身的限制,使用ASP来开发ArcIMS应用的会越来越少。
Ajax及其他
目前流行的地图应用是Ajax客户端,比较“老土”的ArcIMS似乎已经很落后了。但如果了解现今网络地图的基本原理,也了解WebGIS的架构和原理,那么,使用ArcIMS作为后端,开发一个类似的应用也不是难事。国外已经有人在做了,推荐一个站点:http://www.mapdex.org/blog/
本文的后续版本也许也会涉及这个话题。
总结
由本文的叙述,我们可以得出下面一些结论:1. ArcXML,深入编程需要了解ArcXML,因为很多操作必须自己写ArcXML来请求Application服务器,特别是对于.net Link这样的API;
2. JavaScipt,其实对于所有的WebGIS开发,这点都必不可少;客户端操作,自定义的操作,和其他应用在UI的集成,都需要使用JS。
3. 服务器端开发技术,需要的不多,大概看看书就可以照猫画虎了。
4. 由于目前ESRI的主要精力在ArcGIS系列上,因此ArcIMS下一版本的.net Link等是否会得到加强,目前还不得而知。
5. 对于.net运行时,1.1和2.0笔者使用好像都可以,毕竟只是一个程序集的事情,而且要做的事情不多,估计是兼容的。
6. 最后,ESRI的很多产品,由于其历史“悠久”和用户众多,因此寻找有关问题的答案还是很容易的,只要可以上网,有Google可用,大多问题都有答案。