构建一个基于数据库应用:ZK新手的指南

试着运行例子
1.下载todo.zip 文件 并且解压里面的war包文件和一个文件夹。
2.部署war包到Tomcat下$TOMCAT_HOME/webapps/ 目录下 Tomcat会自动解压war包。
3.复制hsqldb文件夹 (数据库文件)到磁盘的根目录下面(例如 c:\)。
4.启动tomacat。
5.打开你的浏览器,访问http://localhost:8080/todo/todo.zul(端口号是在tomcat配置文件里面配置的)你将看到下面的这个截图:

功能描述:

1. 上图所示按钮所对应的事件,当按下“Add“按钮的时候,增加一条记录到数据库。

2. 选择表格中任意一行将显示该行记录的所有字段信息,可以点击“Update”按钮去更新字段信息。

3. 选择表格中任意一行,点击“Delete”按钮去删除选择的记录。

用户界面:

你的第一个ZK组件

第一步是创建一个扩展名为.ZUL文件,我们把它命名为todo.zul,然后把todo.zul 放到web的根目录下面,例如:$TOMCAT_HOME/webapps/ProjectName/ 。
你可以向定义HTMl 组件一样在定义ZK组件在todo.zul文件中 向下图所示,定义一个窗口组件:

<window title="To do list" width="640px" border="normal"> </window>

这个时候 打开你的Tomcat ,用浏览器浏览地址为:http://localhost:8080/todo/todo.zul ,这个时候将会出现一个窗体,窗体名称为To do List。

ZK中所有的东西都是组件,你可以改变组件的属性值。例如你可以改变title,width,border 等属性值在窗体组件中。这个是非常简单明了,现在你就可以试试改变这些属性,看一下效果。

ZK组件的等级关系

接下来,我们就要使用更多的ZK组件来丰富我们的页面。现在我们需要一个显示数据的表格,我们可以定义一个listbox(列表)组件,这个组件可以显示和修改我们的数据。 Listbox组件需要有结束标示,如下图所示
<window title="To do list" width="640px" border="normal"> <listbox id="box" multiple="true" rows="4"> </listbox> </window>

在这个例子当中,listbox(列表)组件成为了window(窗体)组件的一个子组件。
确实,这种情况在ZK组件中我们称之为等级(包含)关系。在实际的开发页面的时候,如果你错误的定义,组件将会出现页面异常。
比如说,你把window(窗体)组件作为listbox的一个子组件,就会出现页面异常。

嵌套组件:

定义一个listbox,我们用Id(id=“box”)描述控件的唯一性。所以我们可以用“box”来引用定义的listbox组件。 Listbox是个嵌套组件,他可以包括两种子组件:listhead(列表头),listitem(列表项),如下图所定义:

<window title="To do list" width="640px" border="normal"> <listbox id="box" multiple="true" rows="4"> <listhead> </listhead> <listitem> </listitem> </listbox> </window>

我们还没有完成。我们在第一三个表头组件来表示三列:“Item”,“Priority”,“Date”,
注意组件的结束符。

<window title="To do list" width="640px" border="normal"> <listbox id="box" multiple="true" rows="4"> <listhead> <listheader label="Item" /> <listheader label="Priority" width="50px" /> <listheader label="Date" width="90px" /> </listhead> <listitem> </listitem> </listbox> </window>

好了,看看界面效果吧:

现在,我们在表格中定义了三列,表格中的每一行需要三个字段来填充。定义三个listcell(单元格)组件包含在listitem(列表项)中,如下图所示:

<window title="To do list" width="640px" border="normal"> <listbox id="box" multiple="true" rows="4"> <listhead> <listheader label="Item" /> <listheader label="Priority" width="50px" /> <listheader label="Opened" width="90px" /> </listhead> <listitem> <listcell/> <listcell/> <listcell/> </listitem> </listbox> </window>

列表组件的嵌套结构如下图所示:

+listbox +listhead listheader +listitem listcell

输入组件:

为了显示列表三个字段,我们需要输入信息,包括Item字段 ( 文本内容 ),prority字段(数值型) date 字段 (日期型)。
要完成以上的工作,我们需要定一个 textbox(文本框),一个inputbox(输入框)和一个databox(日期选择框)三个组件,如下图所示:

<window title="To do list" width="640px" border="normal"> <listbox id="box" multiple="true" rows="4"> <listhead> <listheader label="Item" /> <listheader label="Priority" width="50px" /> <listheader label="Opened" width="90px" /> </listhead> <listitem> <listcell/> <listcell/> <listcell/> </listitem> </listbox> Item:<textbox id="name" cols="50" /> Priority:<intbox id="priority" cols="1" /> Date:<datebox id="date" cols="8"/> <button label="Add" width="36px" height="24px"/> <button label="Update" width="46px" height="24px"/> <button label="Delete" width="46px" height="24px"/> </window>

看一下现在的页面效果:

布局组件:

我了区分三个输入框在列表框显示位置,我们可以定义个groupbox(分组框)组件给输入组件分组,同时groupbox的边框会环绕在输入组件四周:

<window title="To do list" width="640px" border="normal"> <listbox id="box" multiple="true" rows="4"> <listhead> <listheader label="Item" /> <listheader label="Priority" width="50px" /> <listheader label="Opened" width="90px" /> </listhead> <listitem> <listcell/> <listcell/> <listcell/> </listitem> </listbox> <groupbox> <caption label="Event" /> Item: <textbox id="name" cols="50" /> Priority: <intbox id="priority" cols="1" /> Date: <datebox id="date" cols="8"> <button label="Add" width="36px" height="24px"/> <button label="Update" width="46px" height="24px"/> <button label="Delete" width="46px" height="24px"/> </groupbox> </window>

为了分组组件,我们可以定义个标题。这个标题标签处于groupbox组件的顶端,这个标题很向HTML的 legend标签,页面效果如下所示:

持久层

在下面的章节中,我们首先介绍下数据库概要(database schema)和领域对象(domain Object)及Dao对象。

数据库概要:

我们把数据持久化到数据库的表中,需要相应的在数据库建立四个字段:id,name,prority,date 数据库字段,设计如下图所示:

 

FieldType
idvarchar(50)
namevarchar(50)
priorityint
datedate

领域对象:
根据上面的数据库表字段,我们可以封装成需要的领域对象。

public class Event { private String id; private String name; private int priority; private Date date; public Event(){} public Event(String id,String name,int priority,Date date){ this.id = id; this.name = name; this.priority = priority; this.date = date; } //getter and setter methods are ommited, please refer to the source code. }

Dao 对象:

为了与数据库简单的交互,我们需要Dao 对象。Dao对象里面封装了几个方法:findAll(),delete(),insert(),update()。

public class EventDAO { private String url = "jdbc:hsqldb:file:/hsqldb/event"; private String user = "sa"; private String pwd = ""; public EventDAO() { try { Class.forName("org.hsqldb.jdbcDriver"); } catch (ClassNotFoundException e) { e.printStackTrace(); } } //The implementation is ommited, please refer to the source code. public List findAll(){} public boolean delete(Event evt){} public boolean insert(Event evt){} public boolean update(Event evt){} }

台界面与后台数据库进行交互

根据我们的需求,我们想实现增加,修改,编辑,删除事件。在下面的介绍当中,我们会学习到如何实现前台与后台数据库之间的交互。
java代码配合ZK组件使用

ZK众多特性中,有一项是在zul页面当中可以支持java代码。 ZK有三点规定要求:直接可以在页面中嵌入java代码;可以把java代码放在独立的文件中;或者页面文件直接引用编译后的class文件;当然,本指南是按照第一种规定以方便解释。
Zul页面嵌入java代码:

首先,我们需要从数据库中加载数据。我们可以定义标签,在标签里面嵌入我们java代码。 <zscript>元素专门定义脚本的标签。我们可以在ZUL页面定义。这里可以定义全局的变量和方法,也可以实例与数据库连接的DAO对象,我们将把查询的结果放到List中。
在<zscript>中定义的全局变量可以通过el表达式访问。你可以使用el表达式在ZUML页面的任意地方。El表达式的语法标示:${expr}
初始连接数据库:

<window title="To do list" width="640px" border="normal"> <zscript> import events.Event; import events.EventDAO; import java.util.ArrayList; //fetch all events from database EventDAO evtdao = new EventDAO(); List allEvents = evtdao.findAll(); </zscript> <listbox id="box" multiple="true" rows="4"> <listhead> <listheader label="Item" /> <listheader label="Priority" width="50px" /> <listheader label="Opened" width="90px" /> </listhead> <listitem> <listcell/> <listcell/> <listcell/> </listitem> </listbox> <groupbox> <caption label="New" /> Item: <textbox id="name" cols="50" /> Priority: <intbox id="priority" cols="1" /> Date: <datebox id="date" cols="8"> <button label="Add" width="36px" height="24px"/> <button label="Update" width="46px" height="24px"/> <button label="Delete" width="46px" height="24px"/> </groupbox> </window>

使用forEach循环:

下一部就是读取数据库存储的字段显示到listbox,使用forEach循环。ForEach循环属性是为了用户批量控制组件。
如果你显示字段的集合,ZK Loader(zk 加载器)将创建一些相同的组件去显示这些字段,每个变量代表一个存储在集合中的对象的实例,我们可以使用el表达式去调用对象的getter方法找回他们的属性,如下图所示:

<window title="To do list" width="640px" border="normal"> <zscript> import events.Event; import events.EventDAO; import java.util.ArrayList; //fetch all events from database EventDAO evtdao = new EventDAO(); List allEvents = evtdao.findAll(); </zscript> <listbox id="box" multiple="true" rows="4"> <listhead> <listheader label="Item" /> <listheader label="Priority" width="50px" /> <listheader label="Opened" width="90px" /> </listhead> <listitem forEach="${allEvents}" value="${each}"> <listcell label="${each.name}" /> <listcell label="${each.priority}" /> <listcell label="${each.date}" /> </listitem> </listbox> <groupbox> <caption label="New" /> Item: <textbox id="name" cols="50" /> Priority: <intbox id="priority" cols="1" /> Date: <datebox id="date" cols="8"> <button label="Add" width="36px" height="24px"/> <button label="Update" width="46px" height="24px"/> <button label="Delete" width="46px" height="24px"/> </groupbox> </window>

保存用户输入的数据到数据库中

首先,我们要定义一个“add()”方法在<zscript>中。

<zscript> .... void add(){} </zscript>

增加了“add()“方法后,我们将要完成以下三个任务:
1. 检索用户输入数据
2. 保存数据到数据库
3. Ajax局部刷新页面
检索用户输入数据

ZK允许你在java代码里面访问UI组件。你可以通过ID标识符访问一个组件。
在这个例子中,用户输入的数据需要三个输入控件接收,textbox(id ="name"), intbox(id ="priority"), 和datebox(id="date")。
我们可以通过访问控件的Value属性获取用户输入的值,如下图所示:

name.value; //event name priority.value; //event priority date.value; //event date

保存数据到数据库

一旦我们获取到数据,我们就可以把数据持久化到数据库中:

Event newEvt = new Event(UUID.randomUUID().toString(),name.value,priority.value.intValue(),date.value); evtdao.insert(newEvt); //synchronized data object with database allEvents = evtdao.findAll();

Ajax刷新页面

难以置信,ZK允许我们通过java代码实现Ajax技术刷新页面。既然这样,我们使用java代码插入一项到listbox中,ZK将自动刷新页面:

//insert a new Event into the listbox Listitem li = new Listitem(); li.setValue(newEvt); li.appendChild(new Listcell(name.value)); li.appendChild(new Listcell(priority.value)); li.appendChild(new Listcell(new SimpleDateFormat("yyyy-MM-dd").format(date.value))); box.appendChild(li);

appendChiild()方法是插入子项的方法。
完整的代码如下所示:

<window title="To do list" width="640px" border="normal"> <zscript> import events.Event; import events.EventDAO; import java.util.ArrayList; import java.text.SimpleDateFormat; import java.util.UUID; //fetch all events from database EventDAO evtdao = new EventDAO(); List allEvents = evtdao.findAll(); void add(){ //insert into database Event newEvt = new Event(UUID.randomUUID().toString(),name.value,priority.value.intValue(),date.value); evtdao.insert(newEvt); //synchronized data object with database allEvents = evtdao.findAll(); //insert a new Event into the listbox Listitem li = new Listitem(); li.setValue(newEvt); li.appendChild(new Listcell(name.value)); li.appendChild(new Listcell(priority.value)); li.appendChild(new Listcell(new SimpleDateFormat("yyyy-MM-dd").format(date.value))); box.appendChild(li); } </zscript> <listbox id="box" multiple="true" rows="4"> <listhead> <listheader label="Item" /> <listheader label="Priority" width="50px" /> <listheader label="Opened" width="90px" /> </listhead> <listitem forEach="${allEvents}" value="${each}"> <listcell label="${each.name}" /> <listcell label="${each.priority}" /> <listcell label="${each.date}" /> </listitem> </listbox> <groupbox> <caption label="New" /> Item: <textbox id="name" cols="50" /> Priority: <intbox id="priority" cols="1" /> Date: <datebox id="date" cols="8"> <button label="Add" width="36px" height="24px"/> <button label="Update" width="46px" height="24px"/> <button label="Delete" width="46px" height="24px"/> </groupbox> </window>

ZK组件中的注册事件监听

来自页面90%以上的反馈触发了用户的动作。“add()”方法没有异常,这个方法仅当我们单击“add”按钮才会被调用。
确定按钮是否被单击,我们要定义个一个 OnClick的事件来监听按钮组件。用户如果单击“add”按钮的时候,将调用add()方法。
是不是很简单明了? 再次,我们看到了ZK提供了非常简单的解决方式:
<button label="Add" width="36px" height="24px" onClick="add()" />

其他的控制代码:
其余的控制代码在下面列出:
o delete(),从数据库删除一条记录,更新listbox显示
o update(),更新数据库的一条记录,更新listbox显示
o move() , 从listbox中移除数据
o cleargp(),置空groupbox里面的输入组件的内容

<zscript> import events.Event; import events.EventDAO; import java.util.ArrayList; import java.text.SimpleDateFormat; import java.util.UUID; //fetch all events from database EventDAO evtdao = new EventDAO(); List allEvents = evtdao.findAll(); void add(){ //insert into database Event newEvt = new Event(UUID.randomUUID().toString(), name.value,priority.value.intValue(),date.value); evtdao.insert(newEvt); //synchronized data with database allEvents = evtdao.findAll(); //insert a listEvent into the listbox Listitem li = new Listitem(); li.setValue(newEvt); li.appendChild(new Listcell(name.value)); li.appendChild(new Listcell(priority.value.toString())); li.appendChild(new Listcell(new SimpleDateFormat("yyyy-MM-dd").format(date.value))); box.appendChild(li); } void update(){ //update database Event editEvt = (Event)box.selectedItem.value; editEvt.setName(name.value); editEvt.setPriority(priority.value); editEvt.setDate(date.value); evtdao.update(editEvt); //update listbox List children = box.selectedItem.children; ((Listcell)children.get(0)).label = name.value; ((Listcell)children.get(1)).label = priority.value.toString(); ((Listcell)children.get(2)).label = new SimpleDateFormat("yyyy-MM-dd").format(date.value); } void delete(){ evtdao.delete((Event)box.selectedItem.value); box.removeItemAt(box.getSelectedIndex()); cleargb(); } void move(){ name.value = ((Event)box.selectedItem.value).getName(); priority.value = ((Event)box.selectedItem.value).getPriority(); date.value = ((Event)box.selectedItem.value).getDate(); } void cleargb(){ name.value = null; priority.value = null; date.value = null; } </zscript>

注册统一的监听事件:

最后一步我们将注册统一的组件监听事件去调用我们写的方法
o 在“delete”按钮上注册 onClick监听事件
o 在“edit”按钮上注册onClick监听事件
o 在 listbox组件上注册onSelect监听事件

<window title="To do list" width="640px" border="normal"> <zscript> //the implementation part is ommited, please refer to the above listing. void add(){} void delete(){} void update(){} void move(){} void cleargb(){} </zscript> <listbox id="box" multiple="true" rows="4" onSelect="move()"> <listhead> <listheader label="Item" /> <listheader label="Priority" width="50px" /> <listheader label="Opened" width="90px" /> </listhead> <listitem forEach="${allEvents}" value="${each}"> <listcell label="${each.name}" /> <listcell label="${each.priority}" /> <listcell label="${each.date}" /> </listitem> </listbox> <groupbox> <caption label="Event" /> Item: <textbox id="name" cols="25" /> Priority: <intbox id="priority" cols="1" /> Date: <datebox id="date" cols="8" /> <button label="Add" width="36px" height="24px" onClick="add()" /> <button label="Update" width="46px" height="24px" onClick="update()" /> <button label="Delete" width="46px" height="24px" onClick="delete()" /> </groupbox> <window>

总结:

这个指南包含了编写一个简单web应用的ZK基本技术。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值