(在下次的與db4o 結合時,再也不需要 XStream 了:),現在我們一起享受沒有 xml 的 OpenLaszlo 吧!)
OpenLaszlo 是一個允許你在包括 Flash 和 DHTML 在內的多個運行時平臺構建豐富因特網應用程序(rich internet applications,RIA)的開發平臺。你可以利用基于 XML 的 LZX 語言來聲明構建用戶界面并利用 ECMAScript 實現應用程序的動態部分。這和傳統的 HTML+JavaScript 的配合非常類似。
接收非 XML 數據
OpenLaszlo 通常希望你提供的數據是 XML 格式或符合 XML 特性的數據,比如 UI data-binding 組件就依賴這種格式。但是,有某些情況你可能更愿意采用其他數據格式。例如 JSON,作為一種數據交換格式它已經越來越在 Ajax 應用程序中流行了。也許你正在期待 OpenLaszlo 能使用已存在的或是你自己寫的基于 JSON 的服務。
從 OpenLaszlo 3.1 發布開始,可以通過 XMLHttpRequest 類完成數據請求而不必一定是 XML 格式。在使用 XMLHttpRequest 類之前你應該把以下內容引入到 OpenLaszlo 應用程序的 canvas 中。
該類的行為看上去很像經典的 DHTML Ajax 應用程序,比如:
??var?url?=?"http:/yourservice";?//?the?single?slash?is?mandatory?in?OpenLaszlo
??var?req?=?new?XMLHttpRequest();
??req.onreadystatechange?=?processRequestChange;
??req.open("GET",?url,?true);
??req.send(null);
}
先構建一個新的 XMLHttpRequest 實例,注冊回調函數然后執行請求流程,通過實際的 URL 打開請求然后發送到服務器。
回調函數的實現有點像你曾經經歷過的 Ajax 應用程序:
??//?check?if?the?data?transfer?is?complete
??if?(4?==?request.readyState)?{
????//?process?the?reponse?text?if?the?request?was?successful
????if?(200?==?request.status)?{
??????var?text?=?request.responseText;
??????//?


????}
??}
}
它用這種方式幫助你處理接收到的文本數據來為應用程序服務。
采用 JSON
接下來的文章將利用 Java 構建一個非常簡單的 JSON 服務,并在 OpenLaszlo 客戶端使用并異步顯示。
利用 Java 構建 JSON
我盡量避開服務器端 Java 技術的爭論,并假設你選擇的框架可以輸出“text/plain” mime-type 文本數據。
數據是我們將要顯示的“Person”bean:
??private?String?name;
??private?int?age;
??public?void?setName(String?name)?{?this.name?=?name;?}
??public?String?getName()?{?return?name;?}
??public?void?setAge(int?age)?{?this.age?=?age;?}
??public?int?getAge()?{?return?age;}
}
我們將創建 person 實例并為它生成 JSON 數據。有很多 Java 庫可以完成這個工作,但現在我選擇的是 SOJO(Simplify Old Java Objects),這是因為它的設置和使用都非常簡單。
下面是用 Java 寫的服務器端 JSON 服務代碼:
person.setName("Geert?Bevin");
person.setAge(32);
Object?json?=?new?JsonSerializer().serialize(person);
//?output?the?json?data?as?a?string?response
在 OpenLaszlo 中解析 JSON
OpenLaszlo 沒有解析 JSON 的能力,但是幸運的是 Oliver Steele 開發了一個庫來實現。你可以從他的個人站點獲取。下載并解壓縮后,把 json.js 文件放在你的 web 目錄并把下面的代碼添加進 OpenLaszlo canvas 以激活對 JSON 的支持:
現在你可以解析從 XMLHttpRequest 收到的文本數據了,再進行簡單的函數調用就可以得到從服務器端來的 JSON 對象結構。添加下面這行代碼到上面我們創建的 processRequestChange 函數:
“result”變量是一個包含了你獲取到的 person bean 屬性值的數組:
var?person_age?=?result.age;
與 GUI 結合
要包裹上面的數據,我要構建一個簡單的含有按鈕的 OpenLaszlo 界面來觸發 JSON 服務請求。當按鈕被點擊,兩個 text 文本字段將顯示接收到的數據。
構建控制器和界面
添加如下 LZX 代碼片段到你的 canvas 標簽:
??<vbox?id="mainArea"?inset="10"?spacing="10">
????<button?onclick="doXhrRequest()">Get?data</button>
????<hbox?name="personName">
??????<text><b>Name:</b></text>?<text?name="value"/>
????</hbox>
????<hbox?name="personAge">
??????<text><b>Age:</b></text>?<text?name="value"/>
????</hbox>
??</vbox>
</hbox>
?????????
你會發現當按鈕點擊后,我們在本文開頭創建的 doXhrRequest 函數就被執行了。
要在 text 文本字段顯示 processRequestChange 函數解析 JSON 后返回的數據,我們只要簡單的改變對應的界面元素 text 屬性即可:
mainArea.personAge.value.setAttribute("text",?person_age);
優雅的處理網絡延遲
既然是以異步方式處理請求,那么在點擊按鈕后數據到達還需要些時間,這是網絡延遲導致的。這讓用戶感到沮喪,并給應用程序留下緩慢和遲鈍的印象。一個良好的方式是當請求不能立即完成時顯示繁忙狀態指示標識。在本例中,如果數據返回超過 200 毫秒,那么就漂浮一個較透明的玻璃窗口(glass pane)在界面上,寫上“Loading...”提示。下面的 LZX 片段創建了該玻璃窗口:
??????????opacity="0.7"?width="100%"?height="100%">
??<text?align="center"?valign="middle"?fgcolor="#ffffff">Loading

</view>
??????????
在 canvas 標簽關閉之前插入這段代碼,這樣就可以懸浮在任何 GUI 元素之上了。注意在默認時 'visible' 屬性被設置為 false。當要顯示玻璃窗口時可以改變該屬性值實現。
那么,一旦請求發起,我們要初始化一個記時器來實現在 200 毫秒后玻璃窗口的顯示。這個工作可以借由 XMLHttpRequest 類的 readyState 屬性值實現,請參考類文檔詳細了解。根據我們的用例,需要檢查該屬性值是否為 1,以確認請求是否發起。這些條件判斷加在 processRequestChange 函數的開頭:
if?(1?==?request.readyState)?{
??//?create?the?delegate?if?is?doesn't?exist?yet
??if?("undefined"?==?typeof(canvas.loadingMsgDel)?||
????!canvas.loadingMsgDel)?{
????canvas.loadingMsgDel?=?new?LzDelegate(canvas,?"showLoadingMessage");
??}
??//?intiate?or?reuse?a?timer
??LzTimer.resetTimer(canvas.loadingMsgDel,?200);
}
代碼使用了委派類(LzDelegate),主要是為了把事件綁定到方法。該事件用來判定是否啟動定時器,接著 showLoadingMessage 方法將在 200 毫秒后被 canvas 實例調用。實現該方法很簡單,下面看到的代碼片段要在 canvas 標簽中添加:
??this.loadingMessage.setAttribute("visible",?true);
</method>
上面的代碼把加載消息(玻璃窗口)設置為可視。
最后,當數據返回或請求時間小于 200 毫秒時中斷定時器并隱藏該消息。要實現這樣的操作只需要添加兩行代碼到 processRequestChange 函數的初始化條件中:

??if?(4?==?request.readyState)?{
????//?disable?a?pending?loading?message?or?hide?it?if?it's?showing?already
????LzTimer.removeTimer(canvas.loadingMsgDel);
????canvas.loadingMessage.setAttribute("visible",?false);
????//?process?the?reponse?text?if?the?request?was?successful
????if?(200?==?request.status)?{
??????

?????????
結論
利用 OpenLaszlo 的 XMLHttpRequest 類和使用 JSON 服務處理任意文本數據是很簡單的。當然,我的還很簡陋并且沒有用到數據綁定組件。在 OpenLaszlo 4.0(2007 第一季度發布)發布之后,數據集組件抽象程度更高了,統一了與結構化數據的交互方式。即便那樣,你只需直接更新需要的可視化元素即可。
資源
OpenLaszlo 項目網站:http://www.openlaszlo.org
OpenLaszlo 4.0 結構:http://www.openlaszlo.org/legals
OpenLaszlo 軟件工程師指南:http://www.openlaszlo.org/lps/docs/guide
JSON 格式:http://www.json.org
SOJO Java 庫:http://sojo.sourceforge.net
JSON for OpenLaszlo:http://osteele.com/sources/openlaszlo/json
源文件:在這里下載
請注意!引用、轉貼本文應注明原譯者:Rosen Jiang 以及出處:http://www.aygfsteel.com/rosen