最近一段時間,關心 Web 開發的朋友在網絡上會經常聽到 Ajax 這個 buzzword。使用 Google 搜索,會搜索到無數自稱是 Ajax 的例子。這些例子的作者得意洋洋地展示自己學會了 xmlhttp 之後寫出的 hello world,自以爲已經精通了 Ajax。
Ajax 是 Asynchronous JavaScript + XML 的縮寫,其中用到的主要的技術包括:
基於 XHTML/CSS 標準的展現
使用 DOM 的動態顯示和交互
使用 XML 和 XSLT 的數據交換和處理
使用 XMLHttpRequest 的異步數據獲取
JavaScript 把所有的一切捆綁在一起
作者通過以下這個圖對於傳統的交互模式和 Ajax 交互模式做了一個比較。
我們看到,在傳統的交互模式下,客戶端並無表示邏輯的執行,由服務器端執行所有的表示邏輯,然後把 HTML/CSS 傳給客戶端,客戶端僅僅做簡單的展現。
傳統的交互模式最大的問題就是任何哪怕是微小的交互行爲都需要到服務器端走一趟,這樣所帶來大量的延遲令用戶感覺很不舒服,也降低了用戶的工作效率。可能現在 Web 大量用戶已經習慣了等待一個頁面刷新的無聊時間,可是這不能成爲我們開發者推託有責任改善交互行爲的藉口。假設在用戶使用 B/S 應用之前還使用過 C/S 應用,在 C/S 應用中難道會有這樣可笑的事情發生嗎?
在客戶端多出來了一個 Ajax engine,而且服務器傳給客戶端的已經不再是 HTML/CSS,而是純的 XML 數據,客戶端通過 XMLHttp 向服務器端發送請求。所有的表示邏輯在客戶端通過 JS 腳本來執行,然後通過修改 DOM 來完成展現。
雖然在這個詞出現很多年以前就已經有大量的開發人員採用這種開發模式,不過現在既然出現了這個詞,起到了規範術語的作用。去年在 JavaEye 活動上做 XMLHttp 開發的講座時我感覺自己是相當另類的一個人,因爲那時候還沒有多少 J2EE 開發人員會對 JS 感興趣。現在 Ajax 越來越進入 J2EE Web 開發的主流領域,而且會長期保持它的生命力。
在做這個演講之前,我參考網上的一些資料對 Google Maps 做了一些 hack 的工作。目前已經可以做到除了地圖圖片要從 Google 請求外,其餘所有的數據都在本地運行。
但是因爲 Google Maps 前臺的代碼量比較大,並且是經過混淆的。所以整理這些代碼花費了比較多的功夫。目前這個工作尚未全部完成。因此以下講述的內容僅僅是根據我目前的成果。
1. standards-based presentation using XHTML and CSS;
2. dynamic display and interaction using the Document Object Model;
3. data interchange and manipulation using XML and XSLT;
4. asynchronous data retrieval using XMLHttpRequest;
5. and JavaScript binding everything together.
http://maps.google.com
Google Maps 每一張地圖的請求方式是:
http://maps.google.com/maps?ll=49.29,-123.12&spn=0.017998,0.027586&z=3&hl=en
我們看到每一張地圖有 4 個參數,按照值來算實際上是 6 個。
ll:地圖中心的精度和緯度
spn:地圖的範圍(跨度,分橫向和縱向)
z:地圖的縮放級別
hl:地圖採用的語言
http://mt.google.com/mt?v=.1&x=50&y=20&zoom=4
其中包括幾個參數:
v:當前版本號。.1 被推測爲 0.1 版
x:圖片的 x 索引
y:圖片的 y 索引
zoom:圖片的縮放級別。
因爲瀏覽器有圖片的緩存功能,因此如果你經常查看某個相同地區的地圖的話,久而久之,瀏覽器會緩存大量的圖片,這樣你使用 Google Maps 的性能就會越來越好了。
Google Maps 還有搜索的功能,而且非常強大。我這裏錄製了一個簡單的演示。
Google Maps 還可以完成複雜的搜索,例如搜索 lax 這個地方的旅館,結果爲:
點擊地圖右邊旅館條目,可以在地圖上面出現旅館的說明。這個說明是使用 XSLT 技術產生的。
還可以搜索兩點之間的路徑。例如搜索 jfk to 350 5th ave, new york,得到的結果就是帶有兩點之間路徑路徑的地圖。這裏的路徑在 IE 上是使用 VML 畫的,而在其它瀏覽器上使用後臺自動生成的透明 png 圖片輿地圖圖片疊加產生。因爲 IE 完全是在客戶端完成,所以 IE 的性能會好一些。
這裏有這樣一個 xml 文件的例子。在這裏面實際上只有 center 和 span 是必須的。客戶端的腳本通過中心點位置和地圖跨度自動像服務器請求相應的圖片。
<?xml version="1.0"?>
<page>
<center lat="49.29" lng="-123.12"/>
<span lat="0.017998" lng="0.027586"/>
</page>
其它的公司和個人是否可以使用 Google Maps 的技術?
其它的公司和個人完全可以使用 Google Maps 的服務。目前 Google 尚未對這一服務進行收費。因此你可以從 Google 的服務器上請求圖片,通過在你自己的服務器顯示給客戶。剛纔我做的演示完全是在本地運行的,所有的 xml 數據和 js 腳本全部都在本地,僅僅是貼圖來自於 Google 的服務器。Google 的 JS 腳本是有版權的,我這裏僅僅是出於研究的目的,把腳本下載到本地,做了一些修改以便於研究。對於商業應用,可能不能這樣做,可以在頁面中直接使用 Google 服務器上的腳本。因此使用 Google Maps 的方式就是在你自己的服務器上面生成定製的地圖數據,通過 XMLHttp 請求到客戶端,使用 Google Maps 的腳本解析,然後從 Google 請求貼圖數據。除了你自己的地圖數據外,還可以從其它服務器上獲得地圖數據,例如從 Google 的服務器上獲得數據。不過因爲 XMLHttp 只能從本域獲得數據,爲了獲得來自其它域的數據,需要在服務器端用 Servlet 實現一個代理,這個 Servlet 從其它域得到地圖數據後返回給客戶端。這樣一個 Servlet 寫起來是非常簡單的,只需要幾行代碼。同時在客戶端需要對 XMLHttp 對象做一個包裝,使得新的對象可以請求來自不同域的數據。
1、功能完善,具有常規地圖服務所有的功能。
2、性能優良。用戶幾乎從來不需要長期的等待。
3、支持多種瀏覽器,目前 Google Maps 支持的瀏覽器包括以下這些:
IE 5.5+ (Windows)
Firefox 0.8+ (Windows, Mac, Linux)
Safari 1.2.4+ (Mac)
Netscape 7.1+ (Windows, Mac, Linux)
Mozilla 1.4+ (Windows, Mac, Linux)
Opera 7.5+ (Windows, Mac, Linux)
已經囊括了目前所有主流的瀏覽器。
Google Maps 通過自己開發的一套組件庫封裝了 IE 與其它瀏覽器的差別。主要的差別包括 XMLHttp、XMLDom 對象的創建語法,還有事件處理機制的不同。並且 Google Maps 儘量採用符合 Web 標準的技術,使得針對不同瀏覽器開發分支代碼的情況變得最小。
4、通過大量採用客戶端的技術,放棄了傳統的基於 HTML Form 的交互模式,因此使得用戶獲得了更好的交互體驗。
5、完全的組件化和麪向對象開發。
Google Maps 組件和麪向對象設計的水平是非常高的。所有主要的的控件全部封裝爲對象,使用面向對象的方式進行操作。
因爲 XMLHttp 只能得到本域的數據文件,爲了從其它地方獲得數據文件,可以在服務器端實現一個代理。簡單而言就是實現一個 Servlet,通過這個 Servlet 獲得其它域的數據文件,然後返回給客戶端。
爲此需要爲 XMLHttp 對象做一個包裝。我們來看看具體的包裝技術。
1、JavaScirpt 沒有 Java 那樣的 package 或者 C# 的 namespace 的概念,因此類和函數非常容易重名。這個問題不能僅僅通過制定命名規範來解決。
2、JavaScirpt 中的繼承不是真正的繼承,僅僅是所有的子類對象共享一個父類對象,這個父類對象相當於一個 Singleton,因此必須是無狀態的,不能保留自己的屬性。這個問題使得 JavaScript 難以支持多層繼承,無法構造大的繼承體系。