使用 ZK 框架的富 Internet 应用程序

红薯 发布于 2010/04/09 22:50
阅读 4K+
收藏 10

简介: ZK 是一个用 Java™ 代码编写的开源 Asynchronous JavaScript + XML (Ajax) 框架,使用该框架,您无需编写 JavaScript 代码就可以编写一个支持 Web 2.0 的富 Internet 应用程序。Dojo 等典型的 Ajax 框架拥有一些 JavaScript 库,用于公开某些 API 以进行 “Ajax 化” 调用。另一方面,ZK 使用一个基于 XML 的元定义(meta-definition)来定义用户界面。当客户机请求这个页面时,XML 将转化为 HTML 代码。本文将向您介绍 ZK,通过一个真实的示例来展示其使用方法,这个示例运行在 Apache Tomcat 上并连接到 MySQL 数据库。

简介

您可以将 ZK 看做是没有 JavaScript 的 Ajax。它包含一个基于 Ajax 的、事件驱动的引擎,一组丰富的 XHTML 和 XUL 元素,一种名为 ZUML 的标记语言,这种语言用于创建特性丰富的用户界面。业务逻辑可以通过 Java 代码直接编写并集成到您的应用程序中,并基于事件或组件触发。ZK 最强大的特性是其丰富的、用于用户界面开发的控件库。有意思吧?

首先, 我将更详细地描述前面的术语:

  • XHTML:可扩展超文本标记语言(Extensible Hypertext Markup Language),是 HTML 和 XML 的结合体,结合了 HTML 的威力和灵活性与 XML 的可扩展性。清单 1 提供了一个 XHTML 代码示例。

    清单 1. XHTML 代码示例
    						
    <?xml version="1.0" encoding="iso-8859-1"?>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0
    Transitional//EN" "DTD/xhtml1-transitional.dtd">
    <html xml:lang="en" lang="en" xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <title>Hello ZK</title>
    </head>
    <body>
    <h1>Introducing XHTML</h1>
    </body>
    </html>
  • XUL:XML 用户界面语言(XML User Interface Language),简称 XUL(发音同 “Zool”),是一种由 Mozilla 研发的标记语言,一个用于描述图形用户界面的 XML 应用程序。XUL 能够创建多种元素,比如输入控件、工具栏、菜单、树状图、键盘快捷键等。清单 2 展示了一个 XUL 代码示例。

    清单 2. XUL 代码示例
    						
    <?xml version="1.0"?>
    <?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
    <window id="main" title="My App" width="300" height="300"
    xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
    <caption label="Hello World"/>
    </window>
  • ZUML:ZK 用户界面标记语言(ZK User Interface Markup Language),用于定义富用户界面。由于它基于 XML,因此每个元素都描述组件,而属性描述组件值。清单 3 展示了一个 ZUML 代码示例。

    清单 3. ZUML 代码示例
    						
    <window title="Hello ZUML" border="normal">
    Hello World!
    </window>

获取 ZK

获取和安装 ZK 非常简单。ZK 文档网站上包含大量关于库和如何建立文件夹结构的文档(参见 参 考资料 获取链接)。因此,获取 ZK(包括运行 hello world 应用程序)应该非常简单。

为何要使用 ZK?

ZK 是一个直接 Ajax 实现 — 或者换句话说,一个以服务器为中心的模型。ZK 与其他框架不同,其他框架包含大量令人眼花缭乱的 Ajax 调用细节。另外,Ajax 调用需要大量使用 JavaScript 和相关知识,以便在浏览器(客户机)上操作 Document Object Model (DOM) 并在客户机/服务器通信过程中同步数据。ZK 消除了这些复杂性,使您能够专注于业务逻辑。ZK 的其他好处包括:

  • 丰富的用户界面。
  • Web 服务访问。
  • 组 件数据绑定。
  • 简单但强大的标记语言 ZUML。
  • 由于没有客户机代码,因此具有高度的可维护和可扩展性。
  • 高 度易用性。
  • 提高开发人员生产力。

ZK 应用

为理解 ZK 的工作方式,我们来看一个真实示例。这个示例是一个客户管理应用程序,用户可以通过它进行各种操作,比如添加新客户,编辑客户数据,以及数据库中的客户条 目的软删除(soft deletion)。但是,在深入代码之前,我将描述几个通过 ZK 生成的用户界面屏幕。检查过这些屏幕之后,我将描述 ZK 的架构,它是生成这个出色 UI 的底层引擎。最后,我将介绍这个应用程序使用的详细代码和配置参数。

图 1 展示了这个客户管理应用程序的初始屏幕。


图 1. Manage customer index 页面
Manage Customers 应用程序展示了一个数据电子表格视图,其中包括 ID、Name、Active Date  和 whether the account is deleted。

图 1 展示了在这个应用程序中注册的客户列表。这个列表显示为一个网格,包含 4 列:ID,客户姓名、激活日期和删除标记。可以通过单击列名旁边的按钮对网格中的数据排序(升序或降序)。ID(整数型)、Name(字符串)和 Active Date(日期型)列都支持排序。在本文后面部分,我将解释如何通过使用一个 Comparator 对象来定制排序。这个应用程序还支持分页,如屏幕底部所示。这个页面支持一次显示 5 条记录,并具有移动到下一页或直接移动到特定页面的能力。


图 2. 顶部菜单栏
显示 Register New Customer 和 Exit 菜单的屏幕截图

图 2 展示了这个客户管理应用程序的顶端菜单栏,它使用 ZK 的菜单栏小部件实现,包含 Register New Customer 和 Exit 两个选项。

现在您已经检查了这个示例应用程序的几个用户流,我们现在讨论 ZK 的架构细节。

ZK 内部结构

ZK 应用程序的行为与桌面应用程序类似,因为用户活动通过 Client Engine 自动触发服务器上的事件。反过来,服务器上的组件更新视图以匹配客户机上的视图。客户机(浏览器)只充当一个视图,而应用程序在服务器上运行,并且能够完 全访问数据库、Web 服务等资源。因此,安全不是问题。

ZK 框架中有 3 个主要组件:ZK Client Engine、ZK Loader 和 ZK Update Engine。

  • ZK Client Engine:这是 ZK 的客户端,发送请求到服务器以获取相应的 ZK 响应,这个引擎使用这些响应来更新浏览器中的 DOM。
  • ZK Loader:这个组件基于客户机请求的 URL 生成一个 HTML 页面。
  • ZK Update Engine:也称为 Asynchronous Update (AU) Engine,这个组件负责接收 Ajax 请求并更新 ZK 组件中的对应属性,以便 Client Engine 能够更新浏览器中的视图。


图 3. ZK 架构
显示浏览器和服务器的 ZK 架构图。客户机和服务器通过请求/响应互相对话。

图 3 中描述的流的机制如下:

  • ZK Loader 根据客户机请求的 URL 提供 HTML,包括 CSS、 JavaScript 等。这包括 ZK Client Engine,它负责监控客户端事件,将 ZK Requests 发送到服务器并从服务器接收 ZK Responses。
  • Client Engine 根据 onChangeonClick 等用户动作触发事件。
  • 这些事件调用 ZK Update Engine,该引擎更新 ZK 组件的属性并响应 Client Engine。
  • 接收到这个响应之后,Client Engine 更新浏览器中的 DOM 树,以便用户能够看到这个更新后的视图。

使用 ZK 管理客户

接下来,我将继续介绍创建一个示例应用程序来管理客户的细节。我使用 Eclipse IDE 来展示应用程序的创建,但您可以选择使用任何 IDE。

基本的思路是创建一个动态 Web 应用程序项目并将其指向应用服务器运行时,这在本例中为 Apache Tomcat 运行时。

建立新项目和运行时后,复制图 4 中显示的目录结构。


图 4. 目录结构
zkManageCustomers、src Customer.java 和 CustomerService.java  的包视图,WebContent 下面是 addCustomer.zul、editCustomer.zul、index.zul 和  timeout.zul。

这个客户管理应用程序的目录结构遵循图 4 中描述的目录结构的模式。

注意,这个应用程序的核心文件包含在 WebContent 文件夹中,该文件夹包含以下子文件夹:

  • META-INF —— 包含用于连接到 MySQL 数据库的数据库凭证信息。
  • WEB-INF —— 包含一个库文件夹,其中包含运行应用程序所需的 ZK JAR 文件;它还包含描述数据源的 web.xml 文件。
  • 另外,所有关联 zul 文件和 HTML 文件都包含在 WebContent 文件夹中。这些文件充当应用程序的视图部分,向这个 Web 应用程序提供动态和静态内容。

示例文件 zkManageCustomer.zip(参见 下 载 部分)包含这个应用程序的 zip 版本。它还包含 Eclipse 需要的元数据文件,以便其可以直接无缝地导入该 IDE。

Eclipse 中的 Java 2 Platform, Enterprise Edition (J2EE) 透视图拥有一个 server 选项卡,右键单击该选项卡将显示一个创建新服务器选项。这个服务器可用于从 Eclipse IDE 管理应用服务器。

新 服务器配置好后,新创建的资源需要在服务器上配置。这个服务器配置将部署开发过程中创建的资源。

配置 Tomcat 和 MySQL

示例程序被配置为使用 Tomcat 和 MySQL。但是,您可以轻易将其配置为在另一个 Java 应用服务器(比如 WebSphere)中运行。由于示例程序使用 JDBC,因此它应该能够使用任何受支持的 SQL 数据库,比如 DB2 Express-C,这只需简单地修改连接代码。

要将 Tomcat 连接到 MySQL 数据库,您需要定义一个资源引用。这个元素指定一个资源管理器连接工厂引用的名称。在本例中,它将是由 jdbc/mysql 指定的数据库连接,其类型为 javax.sql.DataSource


清单 4. web.xml 中的资源管理器连接工厂

				
. . .
<resource-ref>
<description>DB Connection</description>
<res-ref-name>jdbc/mysql</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
. . .

 

您还需在 WebContent/META-INF 文件夹下的 context.xml 文件夹中定义一个连接资源,这个文件包含驱动程序名称、jndi 名称、用户名、密码、数据类型和 URL 等属性。


清单 5. context.xml 中的上下文定义

				
. . .
<Context>
<Resource driverClassName="com.mysql.jdbc.Driver"
maxActive="4" maxIdle="2" maxWait="5000" auth="Container"
name="jdbc/mysql" password="" type="javax.sql.DataSource"
url="jdbc:mysql://localhost:3306/customer" username="root"/>
</Context>
. . .

 

客户数据库只有一个表,可 以通过运行清单 6 中的脚本创建。


清单 6. 数据库创建脚本

				
use customer;
CREATE TABLE `customer` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`date` date DEFAULT NULL,
`deleted` tinyint(1) DEFAULT '0',
PRIMARY KEY (`ID`)
);

 

调整应用程序以使用 DB2

要将 Tomcat 连接到一个 DB2-Express C 或另一个 DB2 变体数据库,其配置与使用 MySQL 时的配置非常相似。以下的示例展示 web.xml 中的资源管理器连接工厂的配置:


清单 7. web.xml 中的资源管理器连接工厂

				
DB Connection
jdbc/db2db
javax.sql.DataSource
Container
. . .

 

以下是一个典型的上下文定义示例:


清单 8. 上下文定义

				
. . .
maxActive="4" maxIdle="2" maxWait="5000" auth="Container"
name="jdbc/db2db" password="" type="javax.sql.DataSource"
url="jdbc:db2://localhost:(port)/customer" username="db2admin"/>
. . .

应用程序小结

本文前面简要介绍了这个客户管理应用程序,它提供以下功能:

  • 支持用户操作的仪表板页面,包含一个所有客户的视图。
  • 添 加新客户。
  • 编辑现有客户。
  • 支持客户删除(软删除)。

图 5 展示了应用程序的仪表板页面,默认视图显示数据库中的客户列表。


图 5. 仪表板屏幕
仪表板屏幕的屏幕截图:显示一个电子表格样式的数据布局

仪表板屏幕显示了一个所有已注册客户的列表。在这个客户列表上,用户能够根据 ID 或 Name 进行排序。

index.zul 拥有各种属性,比如 borderlayoutmenubarmenumenupopup,这些属性定义应用程序的观感。


清单 9. index.zul 文件

				

<menubar id="menubar" width="800px">
<menu label="Manage Customers">
<menupopup>
<menuitem label="Register New Customer">
<attribute name="onClick"><![CDATA[
Window win = (Window) Executions.createComponents("addCustomer.zul", null, null);
win.doModal();
win.setTitle("Enter Customer Data");
win.setClosable(true);
win.setMaximizable(true);
]]></attribute>
</menuitem>
<menuseparator />
<menuitem label="Exit" onClick="win.detach()" />
</menupopup>
</menu>
</menubar>

 

如 清单 9 所示,我定义了一个 menubar,菜单标签用于注册新客户。单击这个菜单(onclick) 时,通过另一个名为 addCustomer 的 zul,我使用 Executions 对象实例化一个 Window 对象。我还设置这个属性来创建对话框 modalclosable 等。另外,我还包含了一个关闭应用程序的退出菜单。这个 menubar,以及这些已定义的属性,给这个应用程序提供了一种富 客户端观感。

清单 10 展示了如何使用一个 listbox 元素来填充这个表格,在 listbox 中,我定义了一个模型,将根据这个模型填充表格元素。


清单 10. 定义表格的样例 listbox 元素

				
<listbox id="customerList" model="@{myList}" mold="paging" pageSize="5"
multiple="true" width="800px" rows="${custCount}">
<listhead sizable="true">
<listheader label="Id" sort="auto(id)"/>
<listheader label="Name" sort="auto(name)"/>
<listheader label="Active Date" sort="auto(date)"/>
<listheader label="Deleted?" />
</listhead>
<listitem self="@{each=myList}" onClick="showEdit(self.getLabel())">
<listcell label="@{myList.id}" />
<listcell label="@{myList.name}" />
<listcell label="@{myList.date}" />
<listcell label="@{myList.deleted}"/>
</listitem>
</listbox>

 

分 页功能可以使用 listboxmold 属性激活。另外,基于列标题的排序功能可以通过在 listheader 的 sort 属性上启用 auto 来定义。myList 对象是一个 Customer 对象列表,包括以下一些属性:id namedate 以及 Customer 的 deleted flag。服务返回这个列表,然后 ZK 通过 "each =myList" 迭代这个列表。然后,listcell 标签在 listbox 中显示这个 Customer 对象的每个属性。

此外,为了启用编辑功能,我将一个 showEdit 方法附加到 onClick 事件。

Register customer 对话框实现为一个网格,该网格有两个必填值:Customer name 和 Date。


清单 11. Customer 对话框网格代码

				
<grid fixedLayout="true" width="450px">
<rows>
<row>
<label value="Customer Name" />
<textbox id="customerName" constraint="no empty" />
</row>
<row>
<label value="Date" />
<datebox id="date" constraint="no empty"/>
</row>
<row>
<button label="Save" onClick="submit()" />
<button label="Cancel" onClick="addCustomerWin.detach()" />
</row>
</rows>
</grid>

 

对这个 对话框的必填约束通过使用 "no empty" 指定为约束属性。ZK 还支持定义自定义约束。

当 Save 按钮被单击时,我将一个 Java 方法 submit() 附加到这个事件。这个 submit() 方法接收用户提供的姓名和日期值,并在一个新创建的 Customer 对象中设置这些值。然后,这个对象被传递到服务以添加到数据库。清单 12 显示了这段代码。


清单 12. Save 按钮的 Java 代码

				
void submit() throws Exception {
Customer cust = new Customer();
cust.setName(customerName.getValue());
java.util.Date utilDate = date.getValue();
java.sql.Date sqlDate = new java.sql.Date(utilDate.getTime());
cust.setDate(sqlDate);
com.test.services.CustomerService custSvc = new com.test.services.CustomerService();
custSvc.addCustomer(cust);
Executions.getCurrent().sendRedirect("index.zul");
addCustomerWin.detach();
}



图 6. Register customer
显示客户数据输入弹出窗口的屏幕截图,弹出窗口中带有一条数据验证消息:Customer Name must have a  value.

图 7 显示了一个用于编辑客户姓名或日期的屏幕,以及一个 soft delete 选项。


图 7. Edit/Delete 屏幕
带有一个数据输入弹出窗口的应用程序屏幕截图,其中包含一些数据和一个复选框。

编辑机制与设置 Register customer 代码的方式非常相似。您将名称、日期和删除标记的新值传递到更新服务以更新数据库中的记录。如果您想提供其他帮助,您可以使用清单 13 中的代码来创建一个弹出元素。


清单 13. 弹出元素的代码

				
<row>
<label value="Delete?"/>
<hbox>
<checkbox id="deleted" name="deleted" checked="${cust.deleted}"/>
<label value="whats this?" style="font:9;cursor:help;valign:center"
popup="help"/>
</hbox>
<popup id="help" width="400px">
<html>Checking this box will enable soft delete of the record.</html>
</popup>
</row>

ZK 的开发工具

ZK 的最大优势在于它的工具。一个典型的例子就是 ZK-Studio(一个 Eclipse 插件),它用作一个集成开发环境。它包含的特性包括 ZUL Editor、ZUL Visual Editor、ZK Style Designer 和 DB Form Builder。图 8 显示了 ZUL Visual Editor,它用于创建这个样例项目。


图 8. ZUL Visual Editor
ZUL Visual Editor 的屏幕截图,显示了一个典型的文本编辑器

结束语

本文介绍了 ZK 的特性,这是一个用 Java 代码编写的开源 Ajax 框架,展示了一个在 Apache Tomcat 上运行并连接到一个 MySQL 数据库的简单的真实示例。ZK 框架拥有丰富的组件、一种标记语言、强大的开发工具和详细的文档,而且它是一个以事件驱动的开源 Ajax 框架。因此,ZK 正逐渐成为开发低成本的富 Internet 应用程序的流行选择。

下载本文代码

加载中
1
YANGL
YANGL

这东西还不如extjs靠谱。

0
DEC_LIU
DEC_LIU

ZK插件安装有问题,郁闷

0
bobshi
bobshi

不错,学习了,我最近才发现这个框架.挺好的,就是还不太会用.

0
share_code
share_code

不过 我最近也在应用 ZK 框架   红薯大哥的文章 很有帮助。

0
一号男嘉宾
一号男嘉宾

我还是觉得vaadin比较靠谱

0
铂金小鬼
铂金小鬼

通过用zk两年多的感受,用数据绑定,不如用ui对象程序生成界面,感觉更灵活,更直接!

不一定对啊,大家说呢?

0
bobshi
bobshi

引用来自#7楼“蓄势减肥男”的帖子

通过用zk两年多的感受,用数据绑定,不如用ui对象程序生成界面,感觉更灵活,更直接!

不一定对啊,大家说呢?

你都用两年了,咱初级使用者不敢对此多发言啊,

0
小杨阿哥哥
小杨阿哥哥
最好还是不要学那些用后台生成前台的功能。感觉太业余,浪费服务器性能。
李英权
大多情况下数据库会成为瓶颈,应用服务器计算能力却得不到充分利用(cpu占用率低于60%); 再说就算增加了应用服务器的负担,集群也能很容易伸缩。
返回顶部
顶部