切断 OpenLaszlo 与 XML 数据间的耦合

切断 OpenLaszlo 与 XML 数据间的耦合(翻译)
译者语
(在下次的与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 中。

< include href = " rpc/ajax.lzx " />

该类的行为看上去很像经典的 DHTML Ajax 应用程序,比如:

function  doXhrRequest() {
  
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 应用程序:

function  processRequestChange(request) {
  
//  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:

public class Person {
  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 person  =   new  Person();
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 的支持:

< script src = " json.js " />

现在你可以解析从 XMLHttpRequest 收到的文本数据了,再进行简单的函数调用就可以得到从服务器端来的 JSON 对象结构。添加下面这行代码到上面我们创建的 processRequestChange 函数:

var  result  =  JSON.parse(text);

“result”变量是一个包含了你获取到的 person bean 属性值的数组:

var  person_name  =  result.name;
var  person_age  =  result.age;


与 GUI 结合

要包裹上面的数据,我要构建一个简单的含有按钮的 OpenLaszlo 界面来触发 JSON 服务请求。当按钮被点击,两个 text 文本字段将显示接收到的数据。

构建控制器和界面

添加如下 LZX 代码片段到你的 canvas 标签:

< hbox  inset ="10" >
  
< 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.personName.value.setAttribute( " text " , person_name);
mainArea.personAge.value.setAttribute(
" text " , person_age);

优雅的处理网络延迟

既然是以异步方式处理请求,那么在点击按钮后数据到达还需要些时间,这是网络延迟导致的。这让用户感到沮丧,并给应用程序留下缓慢和迟钝的印象。一个良好的方式是当请求不能立即完成时显示繁忙状态指示标识。在本例中,如果数据返回超过 200 毫秒,那么就漂浮一个较透明的玻璃窗口(glass pane)在界面上,写上“Loading...”提示。下面的 LZX 片段创建了该玻璃窗口:

< view  name ="loadingMessage"  visible ="false"  bgcolor ="#000000"
          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 函数的开头:

//  the request has been started
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 标签中添加:

< method  name ="showLoadingMessage" >
  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

你可能感兴趣的:(切断 OpenLaszlo 与 XML 数据间的耦合)