引言
最早使用的
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進行??蛻舳说拇a由服務器端的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可用,大多問題都有答案。