(在下次的与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;
// use the text
}
}
}
它用这种方式帮助你处理接收到的文本数据来为应用程序服务。
采用 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 </ text >
</ 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.blogjava.net/rosen