(在下次的與db4o 結(jié)合時,再也不需要 XStream 了:),現(xiàn)在我們一起享受沒有 xml 的 OpenLaszlo 吧?。?br />
OpenLaszlo 是一個允許你在包括 Flash 和 DHTML 在內(nèi)的多個運行時平臺構(gòu)建豐富因特網(wǎng)應(yīng)用程序(rich internet applications,RIA)的開發(fā)平臺。你可以利用基于 XML 的 LZX 語言來聲明構(gòu)建用戶界面并利用 ECMAScript 實現(xiàn)應(yīng)用程序的動態(tài)部分。這和傳統(tǒng)的 HTML+JavaScript 的配合非常類似。
接收非 XML 數(shù)據(jù)
OpenLaszlo 通常希望你提供的數(shù)據(jù)是 XML 格式或符合 XML 特性的數(shù)據(jù),比如 UI data-binding 組件就依賴這種格式。但是,有某些情況你可能更愿意采用其他數(shù)據(jù)格式。例如 JSON,作為一種數(shù)據(jù)交換格式它已經(jīng)越來越在 Ajax 應(yīng)用程序中流行了。也許你正在期待 OpenLaszlo 能使用已存在的或是你自己寫的基于 JSON 的服務(wù)。
從 OpenLaszlo 3.1 發(fā)布開始,可以通過 XMLHttpRequest 類完成數(shù)據(jù)請求而不必一定是 XML 格式。在使用 XMLHttpRequest 類之前你應(yīng)該把以下內(nèi)容引入到 OpenLaszlo 應(yīng)用程序的 canvas 中。
該類的行為看上去很像經(jīng)典的 DHTML Ajax 應(yīng)用程序,比如:
??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);
}
先構(gòu)建一個新的 XMLHttpRequest 實例,注冊回調(diào)函數(shù)然后執(zhí)行請求流程,通過實際的 URL 打開請求然后發(fā)送到服務(wù)器。
回調(diào)函數(shù)的實現(xiàn)有點像你曾經(jīng)經(jīng)歷過的 Ajax 應(yīng)用程序:
??//?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;
??????//?


????}
??}
}
它用這種方式幫助你處理接收到的文本數(shù)據(jù)來為應(yīng)用程序服務(wù)。
采用 JSON
接下來的文章將利用 Java 構(gòu)建一個非常簡單的 JSON 服務(wù),并在 OpenLaszlo 客戶端使用并異步顯示。
利用 Java 構(gòu)建 JSON
我盡量避開服務(wù)器端 Java 技術(shù)的爭論,并假設(shè)你選擇的框架可以輸出“text/plain” mime-type 文本數(shù)據(jù)。
數(shù)據(jù)是我們將要顯示的“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;}
}
我們將創(chuàng)建 person 實例并為它生成 JSON 數(shù)據(jù)。有很多 Java 庫可以完成這個工作,但現(xiàn)在我選擇的是 SOJO(Simplify Old Java Objects),這是因為它的設(shè)置和使用都非常簡單。
下面是用 Java 寫的服務(wù)器端 JSON 服務(wù)代碼:
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 開發(fā)了一個庫來實現(xiàn)。你可以從他的個人站點獲取。下載并解壓縮后,把 json.js 文件放在你的 web 目錄并把下面的代碼添加進 OpenLaszlo canvas 以激活對 JSON 的支持:
現(xiàn)在你可以解析從 XMLHttpRequest 收到的文本數(shù)據(jù)了,再進行簡單的函數(shù)調(diào)用就可以得到從服務(wù)器端來的 JSON 對象結(jié)構(gòu)。添加下面這行代碼到上面我們創(chuàng)建的 processRequestChange 函數(shù):
“result”變量是一個包含了你獲取到的 person bean 屬性值的數(shù)組:
var?person_age?=?result.age;
與 GUI 結(jié)合
要包裹上面的數(shù)據(jù),我要構(gòu)建一個簡單的含有按鈕的 OpenLaszlo 界面來觸發(fā) JSON 服務(wù)請求。當(dāng)按鈕被點擊,兩個 text 文本字段將顯示接收到的數(shù)據(jù)。
構(gòu)建控制器和界面
添加如下 LZX 代碼片段到你的 canvas 標(biāo)簽:
??<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>
?????????
你會發(fā)現(xiàn)當(dāng)按鈕點擊后,我們在本文開頭創(chuàng)建的 doXhrRequest 函數(shù)就被執(zhí)行了。
要在 text 文本字段顯示 processRequestChange 函數(shù)解析 JSON 后返回的數(shù)據(jù),我們只要簡單的改變對應(yīng)的界面元素 text 屬性即可:
mainArea.personAge.value.setAttribute("text",?person_age);
優(yōu)雅的處理網(wǎng)絡(luò)延遲
既然是以異步方式處理請求,那么在點擊按鈕后數(shù)據(jù)到達還需要些時間,這是網(wǎng)絡(luò)延遲導(dǎo)致的。這讓用戶感到沮喪,并給應(yīng)用程序留下緩慢和遲鈍的印象。一個良好的方式是當(dāng)請求不能立即完成時顯示繁忙狀態(tài)指示標(biāo)識。在本例中,如果數(shù)據(jù)返回超過 200 毫秒,那么就漂浮一個較透明的玻璃窗口(glass pane)在界面上,寫上“Loading...”提示。下面的 LZX 片段創(chuàng)建了該玻璃窗口:
??????????opacity="0.7"?width="100%"?height="100%">
??<text?align="center"?valign="middle"?fgcolor="#ffffff">Loading

</view>
??????????
在 canvas 標(biāo)簽關(guān)閉之前插入這段代碼,這樣就可以懸浮在任何 GUI 元素之上了。注意在默認時 'visible' 屬性被設(shè)置為 false。當(dāng)要顯示玻璃窗口時可以改變該屬性值實現(xiàn)。
那么,一旦請求發(fā)起,我們要初始化一個記時器來實現(xiàn)在 200 毫秒后玻璃窗口的顯示。這個工作可以借由 XMLHttpRequest 類的 readyState 屬性值實現(xiàn),請參考類文檔詳細了解。根據(jù)我們的用例,需要檢查該屬性值是否為 1,以確認請求是否發(fā)起。這些條件判斷加在 processRequestChange 函數(shù)的開頭:
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 實例調(diào)用。實現(xiàn)該方法很簡單,下面看到的代碼片段要在 canvas 標(biāo)簽中添加:
??this.loadingMessage.setAttribute("visible",?true);
</method>
上面的代碼把加載消息(玻璃窗口)設(shè)置為可視。
最后,當(dāng)數(shù)據(jù)返回或請求時間小于 200 毫秒時中斷定時器并隱藏該消息。要實現(xiàn)這樣的操作只需要添加兩行代碼到 processRequestChange 函數(shù)的初始化條件中:

??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)?{
??????

?????????
結(jié)論
利用 OpenLaszlo 的 XMLHttpRequest 類和使用 JSON 服務(wù)處理任意文本數(shù)據(jù)是很簡單的。當(dāng)然,我的還很簡陋并且沒有用到數(shù)據(jù)綁定組件。在 OpenLaszlo 4.0(2007 第一季度發(fā)布)發(fā)布之后,數(shù)據(jù)集組件抽象程度更高了,統(tǒng)一了與結(jié)構(gòu)化數(shù)據(jù)的交互方式。即便那樣,你只需直接更新需要的可視化元素即可。
資源
OpenLaszlo 項目網(wǎng)站:http://www.openlaszlo.org
OpenLaszlo 4.0 結(jié)構(gòu):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
源文件:在這里下載
請注意!引用、轉(zhuǎn)貼本文應(yīng)注明原譯者:Rosen Jiang 以及出處:http://www.aygfsteel.com/rosen