使用 Google Web Toolkit、Apache Derby 和 Eclipse 构建 Ajax 应用程序,第 1 部分: 梦幻前端
在通往创建在用户 Web 浏览器中运行的动态 Java™Script 应用程序的征途中,Google Web Toolkit(GWT)是举足轻重的一步。使用 GWT,开发人员可以利用熟知的 Java 技术设计用户界面(UI)和事件模型,而 GWT 会完成使代码对所有主流浏览器友好的繁重工作。这是本系列的第一篇文章,介绍 GWT 基础知识,包括 GWT 是怎样使您创建一个 Asynchronous JavaScript + XML(Ajax)应用程序,而且依然在 Java 语言中编写代码的。探索如何创建和运行一个小型的样本 GWT 应用程序 —— 近来十分流行的一项 Web 2.0 新业务,称为 Slicr,在线销售比萨饼。
GWT 使得构建富 Ajax 浏览器客户机界面比构建传统 Java GUI 界面还要轻松。然而,即使是 GWT 这样出色的技术也无法独自构建出一个完整的 Web 应用程序。您还必须有一个服务器上的数据存储和某种类型的框架,以便将数据转换成 GWT 可从服务器传递给其客户的 Java 对象。在这一系列文章中,您将使用 Apache Derby 这个 100% 纯 Java 数据库,可将其嵌入与其余服务器端代码相同的 Java 虚拟机(JVM)之中。
本系列的第一篇文章主要探讨 GWT。在这里,您将了解如何设置 GWT,并创建一个简单的客户机界面来响应用户的操作。后续文章将为您展示如何设置 Derby 数据库,并将 GWT 前端与基于 Derby 的后端连接。最终,您将学会如何将在开发环境之外部署您的系统。
![]() |
|
借 助于 GWT,您可以使用 Java 编程语言开发 Ajax 应用程序。Ajax 应用程序的特色就是丰富、交互式的环境,往往与传统 UI 应用程序相关联。图 1 展示了一个示例 GWT 界面,它效仿了桌面电子邮件应用程序。这个演示程序可在 GWT 的 Web 站点看到。
图 1. GWT 电子邮件演示
![GWT 电子邮件演示](http://www.ibm.com/developerworks/cn/opensource/os-ad-gwt1/demo.jpg)
GWT 最独到的特性就在于:您可以创建 Ajax 应用程序,同时依然使用 Java 语言编写代码。您可以使用自己喜爱的 Java 集成化开发环境(IDE),而更好的事情是,还可以在 Java IDE 中调试您的客户机。可以使用 Java 对象在客户机与服务器之间通信,这样的通信在客户机中比使用 Java applet 时要轻量得多。
从根本上来说,GWT 是一种编译器。它将您编写的 Java 代码转换成 JavaScript 代码,这些代码随后会插入 HTML 页面,并用于运行应用程序的客户端。这样的功能使您免于处理在多种浏览器上支持 JavaScript 代码的细枝末节,从而使您能够专注于程序的界面和交互之上。
当然,如果编译器是 GWT 提供的惟一功能,那也不会令人太过兴奋。幸运的是,它给我们带来的不仅如此。有了 GWT,编译器仅仅是一种交付整个客户机/服务器应用程序架构的机制。其特性包括:
- 一组标准 UI 小部件(widget),外观良好、灵活性高,并且已进行了调优,可在所有主流浏览器(包括 Safari 和 Opera)中工作。
- 一种完全在客户端捕捉并响应事件的事件机制。
- 一个管理 Web 应用程序与服务器间的异步调用的框架。
- 一种创建有状态浏览器历史记录的机制,以使您的 Ajax 应用程序不会因为有可能出现的后退(Back) 按钮行为而变得混乱。
- 一个使用 JUnit 为客户机应用程序编写单元测试的测试框架。
本系列将探索上述特性中的大多数。但首先请下载和安装 GWT。
在本文撰写之时,GWT 的最新版本是 V1.2(本文末尾处的 参考资料 部分给出了下载站点的链接)。Microsoft® Windows® XP、Windows 2000、运行 GTK+ 2.2.1 或更新版本的 Linux® 系统和 Mac SO X 完全支持 GWT。
您下载到的是一个压缩文件。解压缩此文件,然后将得到的目录放在方便的位置。根据版本的不同,各发布版的细节可能会略有不同,但基本元素如下:
- 三个 .jar 文件:名为 gwt-user.jar 的文件包含您将需要在项目 classpath 中使用的用户类,而另一个包含大量编译器代码,文件名为 gwt-dev-windows.jar 或 gwt-dev-linux.jar。第三个文件 gwt-servlet.jar 用于部署。
- 三个命令行实用工具:applicationCreator、junitCreator 和 projectCreator。(在 Windows 上,它们的后缀为 .cmd。)稍后将介绍更多相关内容。
- 一个样本代码目录。
在使用 GWT 时,还有其他一些文件会放在 GWT 主目录中,用于管理临时文件。
既 然您已经下载好了一切,那么接下来的首要任务就是创建一个项目。您将为近来十分流行的一项 Web 2.0 新业务(称为 Slicr)构建一个在线站点,在线销售比萨饼。根据您是否计划使用 IDE,设置 GWT 项目的方法的具体细节会有所不同。就本文目的而言,您将使用 Eclipse,因为它是免费的,而且直接被 GWT 命令行实用工具所支持。
首先使用那些命令行实用工具来创建您的 Eclipse 项目:
- 在您的硬盘上任意选择一个方便的位置,创建一个名为 slicr 的新目录。
- 在新的 slicr 目录下打开一个命令行提示符。
- 键入以下命令(您需要更改斜线和与您的操作系统习惯不符的所有符号):
/projectCreator -eclipse slicr
这条命令将创建 GWT 项目所需的最基本内容。得到的结果是一个新的 src 子目录,另外还有新的 .project 和 .classpath 文件。
您可以就这样先使用建立好的项目,但 GWT 希望能有进一步的结构,您可以通过如下命令来设置它:
/applicationCreator -eclipse slicr com.ibm.examples.client.Slicr
-eclipse slicr 参数是 Eclipse 项目的名称,必须与您在 projectCreator 中使用的相同。(如果不同,在 Eclipse 内启动您的 GWT 应用程序时就会出问题。)最后一个参数是您的应用程序的主类的完全限定类名。需要将最低级别的包命名为 client,但除此之外,您都可以自由选择。
这条命令设置了一些文件。.java 文件是您的主类(以及主类必须创建的所有父目录)。您得到了一个与 client 位于同一级别的 public 目录,此目录包含一个名为 Slicr.html 的文件。上级目录包含一个名为 Slicr.gwt.xml 的重要文件。GWT 还会创建一个供 Eclipse 使用的 Slicr.launch 文件以及一些 shell 脚本。
![]() ![]() |
![]()
|
离成功不远了!现在,您必须将项目迁移到 Eclipse 中。
- 打开 Eclipse,然后单击 File > Import。
- 在出现的窗口中展开 General 树,然后选择 Existing Projects into Workspace。
- 单击 Next,然后单击 Browse 来选择 Slicr 根目录。
- 选中项目,确保未 设置 Copy projects into workspace 选项,您并不想移动项目。
这个过程会将您的代码置入 Eclipse,在这里您可以好好观察代码。GWT 已创建了三个重要的文件。第一个位于 com.ibm.examples 包中,名为 slicr.gwt.xml。这是您的 XML 配置文件。现在,它看上去如清单 1 所示。
清单 1. slicr.gwt.xml
在这个 XML 文档中,您可以为 GWT 应用程序定义模块。模块 是 GWT 代码的基本单位,被客户机使用的 HTML 页面所引用。
public 目录中创建的第二个重要的文件是 Slicr.html 文件。这是实际上作为 Web 应用程序的首页发送给客户机的 .html 文件。默认情况下包含大量您不需要的注释。此文件的核心如清单 2 所示。
清单 2. Slicr.html
Slicr
|
在这一方面,要认识到的最重要的一点就是:最终它将是一个普通的 .html 文件。尽管在其中包含您需要的任何 HTML。在这个 .html 文件中,有四个元素将其标识为由 GWT 使用的文件。包括:
- meta 标记: name 属性必须出现,content属性是模块的完全限定逻辑名。(也就是包含 XML 模块文件的包再加上 XML 的文件名,不带扩展名。)该标记将您的 HTML 页面与特定模块相关联。调用页面将启动模块。(明确地说,该模块中的所有入口点类都被初始化。)
- script 标记:此标记载入一个名为 gwt.js 的文件,这是将 GWT Java 代码转换为 JavaScript 代码时创建的文件之一。由于此文件控制所有客户机代码的加载,所以要运行程序,将这个文件包含进来是非常重要的。
- iframe 标记:准确地包含此标记(准确地编写)允许您的 Web 程序记录历史情况和状态,这也就意味着,您的 GWT 应用程序不会禁用用户的后退(Back)按钮。
- td 标记:这个特殊 .html 文件中的这些标记包含 JavaScript 标识符。这方面没有什么特别不寻常的东西,但随后您会看到,GWT 将这些标识符用作放置元素的地方。
GWT 还为您创建了一个样本 Java 启动类,如清单 3 所示。
清单 3. 样本 Java 启动类
|
目前,关于这个类只有几件事情需要注意。Java 类位于您的 client 包中,表示着它意图被 GWT 编译到 JavaScript 代码中。这会给哪些内容可放在此文件中造成了一些限制,但在大多数时候,其中都是基本的 Java 1.4 代码。所创建的类实现接口 EntryPoint,此接口仅定义了一个方法,即 onModuleLoad()。在载入引用了此模块的 HTML 页面时,GWT 将自动调用此方法。
这个特殊的 EntryPoint 非常简单。它的头两行定义了一个按钮和一个标签。在最后两行中,它使用 RootPanel.get() 方法,将这些小部件与特定的 HTML 页面元素相关联。传递给此方法的参数是元素的 JavaScript ID,与其在 HTML 页面中的定义相同。
在头两行和最后两行之间,您使用 Swing 中用于绑定事件的同一风格来定义一个事件侦听器。在本例中,当您的按钮被单击时,ClickListener 将被调用,并简单地来回切换标签小部件中的文本。
![]() ![]() |
![]()
|
现在,您可以尝试运行 GWT 创建的样本程序。有两种不同的方法可以运行 GWT 程序:Web 模式 和 托管模式(hosted mode)。Web 模式是完全部署模式,在将您的 GWT 程序编译为 JavaScript 代码之后,您将使用这种模式。
在 开发过程中使用的是托管模式,它是一个模拟器,通过它可以同时模拟客户机和服务器代码,在开发时使部署大为简化。(托管模式目前在 Mac OS X 上尚不可用。)如果您正在使用带有调试器的 IDE,那么可以在调试器下于托管模式中运行您的 GWT 程序,这允许您设置断点和变量观察(variable watch),甚至可以在即将编译为 JavaScripy 代码的客户机代码部分中进行设置。毫无疑问,这非常酷,也的确非常有用。在 GWT 中工作时,您将在托管模式中花费许多时间。
有多种调用托管模式的方法,您可任选其中的一种。前面您运行的 applicationCreator 脚本创建了一个 Slicr-shell 脚本,可通过命令行调用它来启动托管模式。在上文中,您看到了如何将您的 GWT 项目导入 Eclipse。在 Eclipse 项目中,可以从 Run 菜单或工具栏选择 Debug 或 Run。在出现的窗口中,单击 Java Application 可看到 Slicr 选项。该选项是由 GWT 创建的一个 Slicr.launch 文件提供的,您会将该文件与项目的其余部分一起导入 Eclipse。这个启动文件为 Eclipse 描述了 classpath 和启动类。当然,一旦运行了启动程序(launcher),在您单击工具栏按钮时它将是默认选择。图 2 展示了实际情况下,该窗口的运行效果。
图 2. 调用托管模式
![调用托管模式](http://www.ibm.com/developerworks/cn/opensource/os-ad-gwt1/eclipse.jpg)
在托管模式下运行时,将出现两个窗口。(请注意,托管模式设置初始化需要占用一分钟左右的时间,特别是在第一次运行时。)第一个窗口如图 3 所示,名为 Google Web Toolkit Development Shell / Port 8888。此窗口包含来自 GWT 的错误和日志消息。使用工具栏,您可以打开一个新的托管浏览器,也可以展开、折叠和清除屏幕上的日志记录。
图 3. 托管模式的 shell 窗口
![托管模式的 shell 窗口](http://www.ibm.com/developerworks/cn/opensource/os-ad-gwt1/shell.jpg)
第二个窗口如图 4 所表,是模拟浏览器。如您所见,它包含来自 slicr.html 页面的静态 HTML,还包括 Slicr.java EntryPoint 类中创建的按钮小部件。单击按钮将切换标签。如果您在设置步骤中进行了某些错误的操作,那么就不会看到这个窗口,而是在 shell 窗口中看到一条错误消息。验证所有名称都是正确的。(特别要主要查看 .launch 文件,验证它指定了正确的项目目录。)
图 4. 托管模式模拟浏览器
![托管模式模拟浏览器](http://www.ibm.com/developerworks/cn/opensource/os-ad-gwt1/slicr_sample.jpg)
就本文而言,我们集中关注在屏幕上获得小部件,并提供一点交互性。您最终将得到如图 5 所示的屏幕,大体上来说,它简单而又实用。
图 5. Slicr
![Slicr](http://www.ibm.com/developerworks/cn/opensource/os-ad-gwt1/slicr_final.gif)
要在页面载入时创建这些小部件,您必须将代码放在 EntryPoint 类的 onModuleLoad() 方法中。清单 4 定义了一些实例数据成员和一个调用 helper 来构建各面板的顶级方法。
清单 4. Module 加载事件处理程序
|
您将所有一切都放在一个 DockPanel 内,这是使用 BorderLayout 的 Swing 面板的 GWT 等价部分。Swing 具有一个 Panel 类和多个布局管理器,而 GWT 具有多个 panel 子类,每个子类都使用自己的算法来安排子小部件的布局。其他面板类还包括 SimplePanel、HTMLTable、FlowPanel 和 StackPanel。创建停靠面板并不困难:setter 会帮助您完成所需的一切工作, 如清单 5 所示。
清单 5. 初始化主面板
|
首先要定义南侧(按钮)面板,因为在请求角落处时,DockPanel 是最先出现、最先被服务的。通过这种方式,南侧的小部件才会在整个面板上运行。您将操作面板构建为一个 HorizontalPanel,它大致上相当于 Swing 中的一个框,如清单 6 所示。
清单 6. 南侧(按钮)面板
|
您使用了 GWT Button 小部件来创建三个按钮,然后将其添加到面板中。还为 Clear 按钮创建了一个 ClickListener,稍后我们将定义它。GWT 划分其事件侦听器的方式与 Swing 不同:ClickListener 侦听且仅侦听鼠标点击。(通常,您会看到侦听器被定义为内嵌匿名类。我发现这种风格难于读取和测试,所以我创建了一个有名称的内部类。)
带有比萨饼类型的面板并不复杂。需要使用 GWT RadioButton 小部件,如清单 7 所示。
清单 7. 西侧(比萨饼类型)面板
Pizza");pizzaTypes.add(label); for (int i = 0; i < PIZZA_TYPES.length; i++) { RadioButton radio = new RadioButton("pizzaGroup", PIZZA_TYPES[i]); clearables.add(radio); pizzaTypes.add(radio); } return pizzaTypes; } |
稍后,您将对数据进行某些更聪明的处理。现在,您使用的是 VerticalPanel,它是 HorizontalPanel 的垂直对应部分。您还使用了 HTML 小部件,这只是一个呈现 HTML 的标签。(本质上,它是一个包围着 HTML 标记的包装器。)RadioButton 构造函数接受两个参数。第一个是单选按钮组的字符串标签,第二个是一个文本标签。您将各个按钮同时添加到面板中和可清除项的实例列表中,这个列表将用于一个侦听器之中。
创建东侧(浇头)面板
浇头面板略微复杂一点。您需要允许用户制作每一半具有不同浇头的一张比萨饼。单击与某种浇头对应的按钮会为两半都选中浇头,但每一半都可单独选中或清除。您需要把一切排列整齐,所以使用一个网格,如清单 8 所示。
清单 8. 浇头网格
Toppings"));Grid topGrid = new Grid(TOPPINGS.length + 1, 3); topGrid.setText(0, 0, "Topping"); topGrid.setText(0, 1, "Left"); topGrid.setText(0, 2, "Right"); for (int i = 0; i < TOPPINGS.length; i++) { Button button = new Button(TOPPINGS[i]); CheckBox leftCheckBox = new CheckBox(); CheckBox rightCheckBox = new CheckBox(); clearables.add(leftCheckBox); clearables.add(rightCheckBox); button.addClickListener(new ToppingButtonListener( leftCheckBox, rightCheckBox)); topGrid.setWidget(i + 1, 0, button); topGrid.setWidget(i + 1, 1, leftCheckBox); topGrid.setWidget(i + 1, 2, rightCheckBox); } toppings.add(topGrid); return toppings; } |
又一次地,您使用了 VerticalPanel 和 HTML 小部件。您将所有的东西都放在了一个 GWT Grid 中,因此在创建时必须设置好网格的大小。网格中的每个单元格都包含纯文本或另外一个 GWT 小部件。对于每一行,创建按钮和两个复选框,然后将其指派给相应的单元格。为按钮添加一个侦听器,随后将复选框放在 clearable 列表中。
设置好小部件后,就该看看那两个已经定义好的侦听器了。其中较为简单的一个是 Clear 按钮的侦听器。该按钮仅仅是遍历 clearable 列表并清除所有内容,如清单 9 所示。
清单 9. 为 Clear 按钮定义的侦听器
|
注意:在 GWT 中,RadioButton 实际上是 CheckBox 的子类。因此上述代码不会触发类转换异常。
浇头按钮的侦听器只是稍微复杂一点。如果未选中任何相关复选框,则此侦听器将选中两个复选框。反之,则清除两个复选框,如清单 10 所示。
清单 10. 为浇头按钮定义的侦听器
private class ToppingButtonListener implements ClickListener {
private CheckBox cb1;
private CheckBox cb2;
public ToppingButtonListener(CheckBox cb1, CheckBox cb2) {
this.cb1 = cb1;
this.cb2 = cb2;
}
public void onClick(Widget sender) {
boolean unchecked = !cb1.isChecked() && !cb2.isChecked();
cb1.setChecked(unchecked);
cb2.setChecked(unchecked);
}
}
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/374079/viewspace-130305/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/374079/viewspace-130305/