OpenLaszlo 4 简介

作者:Paul Barry

用户对 Web 的期望正在改变。现代 Web 用户不再满足于填写表单并等待页面刷新,他们希望像与任何其他桌面应用程序一样与浏览器进行交互——即交互式和即时性。最近,AJAX 及其以 JavaScript 为中心的编程范例使这一点变得更加容易。但是,AJAX 并不是唯一可以提供帮助的技术。当然,还有无处不在的 Flash 技术,但其闭源的传统让社区望而却步。然后,还有 OpenLaszlo。

OpenLaszlo 最初是一项以 Flash 为中心的技术,OpenLaszlo Release 4(以下简称 OpenLaszlo)摆脱了其 Flash 传统,并支持 DHTML 作为额外的部署平台。这意味着用 OpenLaszlo 编写的应用程序可以在任何支持 DHTML 或 Flash SWF 的浏览器中执行,这实际上涵盖了每个操作系统上的每个主要浏览器。顾名思义,OpenLaszlo 是一款开源产品,根据 Common Public License 发布,OpenLaszlo 的创建者 Laszlo Systems 热衷于看到围绕这款主要产品形成强大的开源开发者社区。

OpenLaszlo 被誉为富互联网应用程序 (RIA) 开发平台。它的目标是为基于浏览器的应用程序添加类似桌面的功能,并且它以一种非传统但高效的方式实现了这一目标。在本文中,我将解释如何安装和配置 OpenLaszlo,然后我将展示一些小型示例应用程序,展示 OpenLaszlo 可以提供的一些功能。

安装和配置 OpenLaszlo

OpenLaszlo 是一个 Web 开发平台,构建于 Java SDK 1.4 版之上。OpenLaszlo 打包为 Java Servlet,可以放入任何兼容的 Java Servlet 容器中。Apache Tomcat 服务器随 OpenLaszlo 发行版一起提供,并且已经配置好可以使用,因此我在本文中使用它。无论您是否使用 Tomcat,在尝试安装 OpenLaszlo 之前,仍然有必要安装 Java SDK(假设尚未安装)。如果您使用的是 Debian 派生的 GNU/Linux 版本(像我一样),安装 SDK 1.4 版非常容易

sudo apt-get install j2sdk1.4

非 Debian 发行版的用户应检查其软件包存储库以获取 Java SDK 并进行适当安装。Java SDK 安装完成后,以 root 用户身份编辑 /etc/bash.bashrc 文件,将以下行添加到文件末尾

export JAVA_HOME="/usr/lib/j2se/1.4"
export PATH=$JAVA_HOME/bin:$PATH

这些行有效地允许 Java 程序找到 Java 运行时环境。请务必设置这些环境变量,因为没有它们,任何东西都无法工作。配置好 Java SDK 后,就可以获取 OpenLaszlo 了。从 OpenLaszlo 站点下载最新的压缩 tarball(请参阅资源),然后将其复制到您的 /usr/local 目录

sudo cp openlaszlo-4.0.10-unix.tar.gz /usr/local

在撰写本文时,最新最棒的 OpenLaszlo 是 4.0.10 版本。如果您使用的是较新版本,请务必调整这些说明中的版本号。将目录更改为 /usr/local,然后解压发行版

cd /usr/local
sudo tar zxvf openlaszlo-4.0.10-unix.tar.gz 

这将在 /usr/local 下创建一个 lps-4.0.10 目录,其中包含所有解压到位的 OpenLaszlo 内容。重要的是,在 lps-4.0.10/Server/tomcat-5.0.24/ 下存在 Tomcat 服务器。要启动预配置了 OpenLaszlo servlet 的服务器,请输入

sudo /usr/local/lps-4.0.10/Server/tomcat-5.0.24/bin/startup.sh

这将产生以下输出

Using CATALINA_BASE:   /usr/local/lps-4.0.10/Server/tomcat-5.0.24
Using CATALINA_HOME:   /usr/local/lps-4.0.10/Server/tomcat-5.0.24
Using CATALINA_TMPDIR: /usr/local/lps-4.0.10/Server/tomcat-5.0.24/temp
Using JAVA_HOME:       /usr/lib/j2se/1.4

Tomcat 和 Openlaszlo 现在在端口 8080 上运行。

测试 OpenLaszlo

提供了一个 OpenLaszlo 测试页面,您可以通过在浏览器中输入以下 URL 来访问它:http://localhost:8080/lps-4.0.10/examples/hello.lzx。

这将在几秒钟后在浏览器中显示字符串“Hello Laszlo!”。(第一次,OpenLaszlo 需要一段时间才能加载,但随后的重新加载速度很快。)让您的浏览器查看 HTML 源代码,将显示一个完美形成的 HTML 页面,尽管缺少一些人类可读的空格。

生成的输出是由 OpenLaszlo 应用程序创建的,该应用程序使用一种声明性的、基于 XML 的编程语言 LZX 编写。以下是 hello.lzx 的源代码,它几乎是普通的 XML

<canvas> 
    <text>Hello to Linux Journal from Laszlo!</text>
</canvas>

这个简单的例子说明了 OpenLaszlo 的一个重要点。OpenLaszlo 的编程语言本质上是声明式的,而不是过程式的。这意味着您指定您希望 OpenLaszlo 执行什么,而不是指定 OpenLaszlo 如何执行您希望完成的任务。然后,OpenLaszlo 会找出需要执行的一系列步骤并为您执行它们。(在某种程度上,这与正则表达式的工作方式完全相同,因为您指定要查找的模式,而不是如何找到它。)因此,当您编程 OpenLaszlo 时,您在 LZX 中声明您需要的行为,并且您以 XML 编写 LZX。硬核编程人员可能会认为用 XML 编写代码太笨拙了。但这本身不是代码;它是对所需行为的声明。一旦您理解了这个想法,LZX 和 OpenLaszlo 就变得非常有意义了。

构建 OpenLaszlo 应用程序

所有 OpenLaszlo 应用程序中的根 XML 节点都是 <canvas> 标签,其中包含描述应用程序行为的声明性代码。为了了解这一切是如何工作的,让我们使用一些 LZX 代码,以上面的简单测试应用程序为基础进行构建。创建一个名为 ljhello.lzx 的文件,并将以下 LZX 代码放入其中

<canvas>
  <window title="My First App"
          x="50" y="50"
          height="200" width="500"
          realizable="true">
    <text id="message"
          text="Hello from Linux Journal!"/>
  </window>
</canvas>

保存文件,然后将其复制到 OpenLaszlo 和 Tomcat 服务器可以找到的位置

sudo cp ljhello.lzx /usr/local/lps-4.0.10/Server/lps-4.0.10/

在浏览器中输入 http://localhost:8080/lps-4.0.10/ljhello.lzx 会创建一个可移动、可调整大小的窗口,如图 1 所示。

Introducing OpenLaszlo 4

图 1. 我们的第一个 OpenLaszlo 应用程序:ljhello.lzx

参考 LZX 代码,不难理解为此应用程序指定的内容。我们从一个空白画布开始,然后创建一个窗口,该窗口具有标题、x/y 位置、高度/宽度值以及打开的可调整大小属性。在窗口中,我们要求一些文本,为文本提供标识符和初始值。请注意 LZX 代码中缩进的使用如何自然地帮助描述应用程序的哪些组件与哪些其他组件相关。在浏览器中,可以抓取和拖动以及调整大小生成的窗口。

OpenLaszlo 和数据

出于演示目的,让我们想象我们有一个小型在线商店,希望通过一个美观、现代的基于 Web 的界面来提供对其客户列表的访问。为了提供所需的功能,让我们将数据放入 MySQL 数据库中,并通过 OpenLaszlo 应用程序提供对列表的访问。

首先,以 root 用户身份登录 MySQL 客户端,然后创建一个名为 store 的数据库和一个名为 store_manager 的 MySQL 用户

mysql> create database store;
mysql> use mysql;
mysql> grant all on store.* to store_manager identified by 'passwordhere';

以这个新用户身份登录 MySQL,并创建一个表来保存客户列表

mysql -u store_manager -p store

mysql> create table client_details 
       (
	    id int not null auto_increment primary key,
	    name varchar (64) not null,
	    address varchar (255),
	    contact_tel_no varchar (64),
            email_address varchar (64)
       );

一小部分 SQL 插入语句(格式化以适合此页面)为我们提供了一些要使用的数据

mysql> insert into client_details value ( 0,       \
'Joe Bloggs', '25 Somewhere Street, Anytown, USA', \
'00-1-415-555-3226', 'joe@bloggs.com' );
mysql> insert into client_details value ( 0,       \
'Jane Doe', 'Apt. 2a, 16 Treatsville, Canada',     \
'00-1-416-555-1222', 'jane@idontknow.ca' );
mysql> insert into client_details value ( 0,       \
'Harry Smith', 'P.O. Box 46, Streetstown, USA',    \
'00-1-581-555-9823', 'harry@harrysmith.com' );
mysql> insert into client_details value ( 0,       \
'Julie Jones','CharmsRus, BT Tower, London, UK',   \
'00-44-081-555-2398', 'julie@charmsrus.co.uk' );

数据库表准备就绪,并插入了一些示例数据后,我们接下来需要将数据转换为 OpenLaszlo 可以理解的格式。当与 OpenLaszlo 通信时,您数据的最佳格式是 XML,这应该不会让您感到惊讶。OpenLaszlo 具有一些非常简洁的内置功能,可用于处理 XML 数据。为了演示这一点,我们首先必须安排 MySQL 生成一些 XML 输出。

有很多方法可以做到这一点,我将用 Ruby 编写一个简单的 CGI,它连接到数据库,从所需的表中选择所有数据,并将其转换为 XML。我的程序名为 get_data.rb,将从 Apache 的 CGI 目录执行,该目录在我的系统上是 /usr/lib/cgi-bin。这是我编写的 Ruby 代码

#! /usr/bin/ruby 

require 'cgi'
require 'dbi'

resp = CGI.new

puts resp.header( "text/xml" )

dsn =  "DBI:Mysql:store"
user = "store_manager"
pass = "passwordhere"

sql =  "SELECT * FROM client_details"

DBI.connect( dsn, user, pass ) do |dbh|
    rows = dbh.select_all( sql )
    DBI::Utils::XMLFormatter.table( rows, 
                                    "clients", 
                                    "client" )
end

这段代码很简单。关键行是调用 DBI::Utils::XMLFormatter,它接受 SQL 查询的结果并生成格式正确的 XML。要查看结果,请将 get_data.rb 安装到 Apache 的 cgi-bin 目录(将 get_data.rb 设置为可执行),然后在浏览器中输入以下内容:http://localhost/cgi-bin/get_data.rb。图 2 显示了 get_data.rb CGI 脚本生成的 XML。

Introducing OpenLaszlo 4

图 2. get_data.rb CGI 脚本生成的 XML 输出

要从 OpenLaszlo 应用程序内部访问此数据,只需使用 LZX dataset 标签进行适当的声明即可。这是另一个文件 clients.lzx,它在 OpenLaszlo 窗口中显示每个商店客户的姓名

<canvas>
  <dataset    src="http://localhost/cgi-bin/get_data.rb" 
              name="dataClients"
              request="true" />

  <window     title="Client Listing"
              name="top"
              height="300" width="200"
              x="50" y="50"
              realizable="true">
    <view>
      <text>
        <datapath xpath="dataClients:/clients/client/name/text()"/>
      </text>
      <simplelayout/>
    </view>

    <scrollbar/>

  </window>

</canvas>

与之前的示例一样,其中有一个带有文本的窗口。请注意,文本包含在 LZX 视图中,该视图将文本与称为 simplelayout 的东西组合在一起,simplelayout 是一种内置的 OpenLaszlo 样式,可将文本逐行堆叠。名为 top 的窗口还关联了一个滚动条。dataset LZX 标签告知 OpenLaszlo 应用程序从哪里获取数据 (src)、数据集的名称 (name),并指示应用程序在加载数据后立即获取数据 (request)。datapath 标签是标准的 XML XPath 规范,指向我们要使用的数据集。在本例中,我们要检索 name 标签的文本,该标签包含在内部封闭的 client 标签中,而 client 标签本身又包含在外部封闭的 clients 标签中。回顾图 2,很容易看到我们在此 XPath 说明符中引用的数据。

要试用此应用程序,请将 LZX 文件复制到服务器上的相应目录(使用与 ljhello.lzx 文件相同的目标目录),然后使用以下 URL 在浏览器中启动应用程序:http://localhost:8080/lps-4.0.10/clients.lzx。

这将生成一个 OpenLaszlo 窗口,其中显示了四个客户的姓名,如图 3 所示。

Introducing OpenLaszlo 4

图 3. 在 OpenLaszlo 应用程序中显示姓名列表

添加交互性

虽然有趣,但如果单击客户姓名会在浏览器中生成另一个包含客户其余数据的窗口,则此列表将更有用。安排此行为并不困难。我们需要做的第一件事是为用户在第一个窗口中选择客户姓名时提供一些视觉反馈。将此代码添加到窗口的 <text> 元素

<handler name="onclick">
   client_info.datapath.setFromPointer( this.datapath );
</handler>

<handler name="onmouseover">
   this.setBGColor( 0xBBBBFF );
</handler>

<handler name="onmouseout">
   this.setBGColor( null );
</handler>

这段 LZX 代码突出了 OpenLaszlo 将 JavaScript 嵌入 XML 元素的能力。这段代码指示浏览器执行的操作是,一旦用户单击列表中的姓名,就将名为 client_info 的数据指针设置为当前选定的数据路径。它还在用户将鼠标悬停在客户姓名上时更改背景颜色,从而提供类似桌面的漂亮视觉反馈。但是,client_info 是什么,它指的是什么?它是另一个 OpenLaszlo 窗口,使用以下 LZX 代码定义

<window name="client_info" 
        x="300" y="100"
        width="300" height="200"
        title="Client Specifics">

  <datapath/>
    <text datapath="../address/text()"
          width="100%" 
          multiline="true" />
    <text datapath="../contact_tel_no/text()"
          fontsize="16"/>
    <text datapath="../email_address/text()"
          fontsize="14"/>
    <simplelayout/>

</window>

此窗口具有自己的名称和标题值,以及 x、y、width 和 height 值,这些值最初将其定位在客户列表窗口的右侧。它还具有 datapath 标签,以及三个文本元素,这些元素引用(使用适当的 XPath 规范)我们数据库表中的其他数据元素。我们指定地址使用 client_info 窗口的整个宽度并且可以自动换行,而其他两条数据以不同设置的字体大小显示。当此 LZX 应用程序(名为 clients2.lzx)加载到浏览器中时,客户列表将出现在原始窗口中,并且每当单击客户姓名时,第二个窗口都会刷新以显示当前选定客户的地址、电话号码和电子邮件地址。如果您一直在关注,请注意用户在单击每个客户姓名时如何收到视觉反馈。图 4 显示了一个示例,其中一个客户姓名突出显示(单击),相关详细信息显示在第二个窗口中。

Introducing OpenLaszlo 4

图 4. 显示选定客户的特定详细信息

添加动画

让我们通过为我们的 OpenLaszlo 应用程序添加一些 LZX 动画效果来结束此示例,从而获得一些乐趣。具体来说,每当用户单击第一个窗口中的客户姓名时,除了刷新数据之外,我们还希望第二个窗口向上滚动(收缩)、暂停,然后再向下滚动(增长)。为了实现这一点,我们需要用对动画器的调用来包装 onclick 处理程序代码

<handler name="onclick">
  client_info.winShrink.doStart();
  client_info.datapath.setFromPointer( this.datapath );
  client_info.winGrow.doStart();
</handler>

使用 LZX 指定动画涉及编写 XML。以下是此应用程序(我将其称为 client3.lzx)的收缩和增长 LZX 代码。此代码已添加到第二个窗口的 XML 中

<animatorgroup name="winShrink" 
               start="false" 
               duration="0">
    <animator attribute="height" to="50"/>
    <animator attribute="height" to="50"/>
</animatorgroup>

<animatorgroup name="winGrow" 
               start="false" 
               duration="200">
    <animator attribute="height" to="200"/>
    <animator attribute="height" to="200"/>
</animatorgroup>

我定义了两个 animatorgroup 并为每个 animatorgroup 命名。请注意上面 onclick 处理程序中如何引用 animatorgroup 名称。在每个 animatorgroup 中,我提供了一些计时数据(duration)和窗口高度的新属性值。当窗口收缩时,高度降至 50 像素。当窗口增长时,高度升至 200 像素。组合起来,视觉效果是窗口向上滚动、暂停,然后向下滚动以显示更新的客户详细信息。不幸的是,我无法在屏幕截图中显示这一点,因此您必须尝试一下才能看到实际效果(或相信我的话)。当然,主要的一点是,视觉效果是在没有编写代码本身的情况下实现的。我所做的只是在 LZX 中定义我想要的行为。

了解更多关于 OpenLaszlo 的信息

查看 Laszlo Systems 网站以获取有关 OpenLaszlo 的更多信息(请参阅资源)。请务必花 30 分钟观看提供的非常棒的截屏视频,其中 OpenLaszlo 大师 Adam Wolff 逐步介绍了该技术的一些功能(注意:Adam 的视频启发了本文中的大部分材料)。要了解关于 LZX 的大部分知识,请查看 Manning Publications 出版的书籍:Laszlo in Action(请参阅资源)。本文中介绍的所有 LZX 和 Ruby 代码都可从 Linux Journal FTP 站点下载(请参阅资源)。

资源

OpenLaszlo 主页:www.openlaszlo.org

Laszlo in Action,Manning Publications 出版:laszloinaction.com

文章源代码:ftp.linuxjournal.com/pub/lj/issue171/10071.tgz

Paul Barry (paul.barry@itcarlow.ie) 在爱尔兰卡洛理工学院任教。在他的网站上了解更多关于他所做的事情:glasnost.itcarlow.ie/~barryp

加载 Disqus 评论