使用 Apache Pivot 构建 iTunes 搜索客户端

使用 WTKX 和 Java 技术构建富 Internet 应用程序

Apache Pivot 是用于在 Java™ 环境中构建富 Internet 应用程序(RIA)的开放源码平台。它将现代 RIA 工具箱的高级生产力和可用性特性与作为行业标准的 Java 平台的健壮性结合起来。Apache Pivot 通过利用 WTKX(用于用户界面设计的、基于 XML 的语言)使得可视化应用程序的输出变得十分容易。在本教程中,您将实现一个简单但实用的 Pivot 应用程序,它允许用户对 iTunes Store 执行搜索。

Greg Brown, 高级软件工程师, VMWare

Greg Brown 是 VMware 的技术团队的高级成员。他研究并推广富客户端技术已超过 10 年,包括 Java、Flash、Flex 和 Ajax。他是基于 Java 的富客户端平台 Pivot 的架构师和领导者。他拥有 University of Massachusetts Amherst 的计算机系统工程学士学位。



2009 年 11 月 26 日

开始之前

常用术语

  • Ajax:异步 JavaScript + XML
  • API:应用编程接口
  • CSV:逗号分隔的值
  • GUI:图形用户界面
  • HTML:超文本标记语言
  • HTTP:超文本传输协议
  • JSON:JavaScript 对象表示法
  • JVM:Java 虚拟机
  • REST:具像状态传输
  • UI:用户界面
  • URL:统一资源定位符
  • W3C:万维网联盟
  • XHTML:可扩展超文本标记语言
  • XML:可扩展标记语言

本教程假设您熟悉常见的 Web 开发概念和技术,包括 Java 技术、XML、JSON、JavaScript 和 HTTP。在阅读完本教程之后,您将理解如何轻松地使用这些技术构建 Pivot 应用程序。

关于本教程

像其他 RIA 开发平台一样,Apache Pivot 包含大量使得构建现代 GUI 应用程序更加容易的特性,包括声明性用户界面、数据绑定、视觉效果和渐变,以及 Web 服务集成。Pivot 应用程序是混合使用 Java 技术和基于 XML 的标记语言(WTKX)构建的。Java Virtual Machine 脚本语言也受支持。您可以使用 Java 插件在 Web 浏览器中运行 Pivot 应用程序,或将它们作为独立的桌面应用程序运行(可以离线)。

在本教程中,您将实现一个简单但实用的 Pivot 应用程序,它允许用户对 iTunes Store 执行搜索。我首先从介绍 Pivot 平台开始,接着概述 iTunes 搜索 API,最后展示演示应用程序。在这个过程中,我将阐述如何:

  • 用 WTKX 创建用户界面声明,它是 Pivot 的基于 XML 的 UI 标记语言
  • 使用 Pivot 对 JSON 系列化的内置支持处理 JSON 数据
  • 在 JavaScript 中处理用户界面事件

先决条件

本教程中的样例代码基于 Pivot 1.3 发行版,该版本需要 Java 6(或更高版本)的 SDK。您可以下载二进制文件或源代码形式的 Pivot 1.3;源代码发行版包含一个 BUILD 文件,它描述如何构建项目。

演示应用程序的源代码随平台一起发行。所有代码样例都在 Apache Software License, Version 2.0 中发行。

查看 参考资料 部分获得下载样例代码、Pivot 1.3、Java 6 SDK 和演示应用程序的链接。


简介

在查看您将在本教程中创建的样例应用程序之前,本小节先介绍 Apache Pivot 和在 Pivot 平台上的应用程序开发。

Apache Pivot 简介

现在 Web 实际上已经成为应用程序交付的标准方法。不过,Web 应用程序的功能性需求开始超越浏览器的功能。尽管添加了脚本支持、动态元素操作和异步服务器通信,在 HTML 中仍然难以创建与桌面应用程序相媲美的用户体验。

RIA 开发平台是连接 Web 和桌面体验的桥梁。使用浏览器插件之后,这些平台允许构建更加类似于原生桌面应用程序的 Web 应用程序,但又可以像基于 HTML 的传统 Web 应用程序那样通过网络进行部署。RIA 还通常引入了视觉效果(比如动画和其他动态行为),以改善总体用户体验。

当今用于构建 RIA 的常见平台包括 Adobe® Flex®、Microsoft® Silverlight™ 和 Sun™ JavaFX™。尽管 Java 仍然是最流行的语言,但这 3 个平台都不支持用 Java 编写 RIA。Flex 应用程序使用 ActionScript 编写的、Silverlight 应用程序使用 .NET 编写的,而 JavaFX 应用程序使用 JavaFX Script 编写的。Pivot 允许使用 Java 平台的开发人员利用他们熟悉的技术和 API 构建 RIA。

Pivot 还为 RIA 开发人员提供真正开源的代替选择。尽管 Flex、Silverlight 和 JavaFX 在某种程度上是开源的,但它们仍然是专用的平台。Pivot 在 2007 年作为 R&D 开始开发,并于 2008 年在 Apache 2.0 许可中作为开源项目发行。Pivot 于 2009 年 1 月份与 Apache Incubator 结合,现在完全由该软件驱动。

Pivot 平台概述

Pivot 提供一组全面的基础类,这些类共同构成了一个框架。Pivot 类按照以下类别进行分组,并且打包到对应的库中并发行:

  • Core —— 一组常见的非 UI 类
  • WTK —— 用于用户界面开发的类,包括窗口、对话框、按钮、列表、文本输入、布局、拖放操作和 XML 标记等
  • Web —— 为与远程数据服务通信提供便利的类
  • Charts —— 向 Pivot 应用程序添加交互式图表功能的类
  • Tools —— 开发工具和实用应用程序

本教程描述的应用程序重点描述 Core、WTK 和 Web 库提供的特性。

演示应用程序

本教程描述的演示应用程序允许用户从 iTunes Store 搜索与特定查询条件匹配的标题。查询被指定为一组字符串词汇,并且匹配条目被显示在一个表视图中。用户从表中选择一个条目以显示标题的缩略预览,然后双击该条目或按 Preview 预播放该条目 30 秒。选择这个例子的原因是,它突出了 Pivot 的许多强项,包括使用 WTKX、JavaScript 轻松构建 UI 和 Pivot 对与基于 JSON 的 REST 服务进行交互的支持。

图 1 是样例应用程序的屏幕截图,是在使用 Cheap Trick 搜索标题时捕获的。

图 1. iTunes Search 演示应用程序
在 iTunes Search 演示应用程序中完成搜索之后的屏幕截图

要获得演示应用程序,参见 参考资料 部分(需要 Java 6 SDK)。单击表中的行将显示搜索结果的缩略图,单击 Preview 将预播放该条目 30 秒。

将在下一个小节中描述的 WTKX 用于建立应用程序的用户界面的初始结构。Java 用于定义 UI 背后的核心逻辑和行为,而轻量级脚本语言 JavaScript 则用于将各个部分合并起来。


Pivot 中的 UI:WTKX

WTKX 是一种用于构建 Pivot 应用程序的、基于 XML 的标记语言。它通常用于定义应用程序的用户界面的结构。由于 XML 文档的层次结构与 Pivot 组件的层次结构紧密对应,所以可视化生成的输出非常容易。不过,实际上您可以使用 WTKX 显式地构造任何类型的 Java 对象树。这个小节简单介绍 WTKX,并突出讲解在样例应用程序中应用它的关键方面。

WTKX 简介

像所有基于 XML 的 UI 标记语言一样,WTKX 依赖于元素属性这两个基础的 XML 概念。让我们看看 Pivot 如何将这些结构映射到 Java 类的实例和属性。

元素

在 WTKX 中,XML 元素表示两样东西之一:类实例或类实例的属性。其标记名以大写字母开头的元素表示类实例,而以小写字母开头的表示类实例的属性。当 WTKX 序列化器(负责加载 WTKX 文件的类)遇到标记名以大写字母开头的元素时,它就认为该标记是 Java 类的名称并创建该类的一个实例。假设元素的名称空间包含该类所属的包的名称。任何以小写字母开头的嵌套元素都被认为是包含应用到该类的属性值。属性元素的名称被转换成类实例公开的 JavaBean 属性的名称。

属性

属性值也被转换成 JavaBean 属性。属性值被作为参数传递给 setter 方法。如果属性的类型为 string,那么就按原样传递该值;不过,如果其类型为基本类型之一(boolean、char、byte、short、int、long、float 或 double)或是它们的包装器等价物之一,那么该值就在调用 setter 方法之前转换成适当的类型。

例如,看看 清单 1 中显示的简单的 JavaBean 类。

清单 1. 简单的 JavaBean 类
view sourceprint?
package com.foo;
 
public class MyBean {
    private String foo = null;
    private int bar = 0;
     
    public String getFoo() {
        return foo;
    }
     
    public void setFoo(String foo) {
        this.foo = foo;
    }
     
    public int getBar() {
        return bar;
    }
     
    public void setBar(int bar) {
        this.bar = bar;
    }
}

这段 WTKX 代码初始化 bean 并调用 foobar setter,将一个 String 值传递到 setFoo() 并将一个 int 值传递到 setBar(): <MyBean xmlns="com.foo" foo="hello" bar="123"/>

清单 2 生成的结果与 清单 1 相同。

清单 2. 生成相同的结果
<MyBean xmlns="com.foo" bar="123">
    <foo>hello</foo>
</MyBean>

注意,bar 属性(property)仍然被指定为一个属性(attribute)。这是因为上述的原始转换过程仅适用于属性(attribute),而不适用于元素值。不过,除了字符串内容之外,元素属性(property)还可以包含复杂类型(例如其他 JavaBean 实例),而属性(attribute)就不可以。

除了类实例化之外,WTKX 还提供许多便于构造用户界面的特性,比如包含、脚本和资源注入。接下来将详细讨论这些特性中的一部分。

应用程序例子

清单 3 显示了用于构造应用程序的用户界面的 WTKX 源代码。根元素是一个 <Window>,它因为使用默认的名称空间而与 org.apache.pivot.wtk.Window 的一个实例对应。这是 Pivot 提供的最基础窗口类型;它没有提供任何额外的修饰,比如标题栏或调整大小处理,而是仅仅当作显示的入门点(Pivot 应用程序中的顶级 UI 构造)。

清单 3. 应用程序的用户界面的 WTKX 源代码
<Window title="Search Demo" maximized="true"
    xmlns:wtkx="http://pivot.apache.org/wtkx"
    xmlns:content="org.apache.pivot.wtk.content"
    xmlns="org.apache.pivot.wtk">
    <content>
    ...
    </content>
</Window>

注意,窗口的 maximized 属性设置为 true;这导致窗口展开并填满应用程序上下文的整个客户端区域。当在浏览器中运行时,它与执行应用程序的 applet 的客户端区域对应;在桌面上,它与应用程序的框架的客户端区域对应。

<Window> 的唯一直接子元素是一个 <content> 元素。该元素的内容被设置为窗口的 content 属性。窗口的内容是一个组件,它的大小总是符合窗口本身的客户端区。在这个例子中,窗口内容是一个 TablePaneTablePane 是一个大致与 HTML 表对应的 Pivot 容器。它将子组件排列在一个由行和列组成的网格中,其单元格是可伸缩的。表的结构由它的 <rows><columns> 集合定义,如 XML 中指定的一样(见 清单 4)。

清单 4. 定义 TablePane 容器
<TablePane styles="{padding:6, verticalSpacing:6}">
    <columns>
        <TablePane.Column width="1*"/>
    </columns>
    <rows>
    ...
    </rows>
</TablePane>

注意 TablePane 元素的 styles 属性。样式用于定制组件的外观,并且在 WTKX 中被指定为 JSON 格式的名/值对集合。所有 WTK 组件都支持 styles 属性,但每个组件都可以支持一组不同的样式,这取决于它们当前的 skin(皮肤是 Pivot 对插入式外观的支持)。在这个例子中,表面板的 paddingverticalSpacing 被分配为值 6 像素。填充区域是指表面板为每个组件周围留出的空间,并且垂直空间是指表面板在行之间留出的空间。

WTKX 文件的剩余部分用于建立应用程序的用户界面的结构。它还定义一些 JavaScript 事件处理程序,将在 事件处理:JavaScript 小节中详细阐述它们。最有趣的是用于呈现搜索结果的 TableView 组件的定义(见 清单 5)。

清单 5. TableView 组件定义
<TableView wtkx:id="resultsTableView">
    <columns>
        <TableView.Column name="itemName" width="1*" headerData="Name"/>
        <TableView.Column name="itemParentName" width="1*" headerData="Album"/>
        <TableView.Column name="artistName" width="1*" headerData="Artist"/>
    </columns>
    ...
</TableView>

表视图定义一组其名称直接与返回的 JSON 数据中的条目属性对应的列。Pivot 的 TableView 组件能够按原样显示 JSON 数据,并且不需要任何数据转换(也支持 CSV 数据)。这使得 Pivot 成为构建可以使用常见数据格式的 REST 客户端的理想平台。让我们看看这是如何实现的。


查询处理:Java + JSON 技术

尽管通常使用 WTKX 定义 Pivot 应用程序的用户界面,但是通常使用 Java 代码定义应用程序的行为。还可以使用脚本编写应用程序的逻辑,这允许开发人员使用流行的 JVM 语言(比如 Groovy 或 Scala)构建一些或所有 Pivot 应用程序。我使用 JavaScript 来定义样例应用程序中的事件处理程序。

JavaScript Object Notation (JSON) 是一种独立于平台的数据交换格式。像 XML 一样,它用于表示结构化数据,但通常能够更好地映射到许多流行的编程语言使用的数据结构,包括 Java 和 JavaScript。它要比 XML 简洁一些,因为它没有结束标记。尽管 JSON 最常用于 Ajax 开发,但任何支持它的平台或语言都可以使用它。Pivot 原生支持 JSON,这使得 JSON 在 Pivot 平台中得到广泛使用,包括资源定义、样式声明和数据交换。

现在您将看到 Java 代码如何从 WTKX 加载 Pivot 应用程序的用户界面,以及如何使用 Pivot 对 JSON 数据的健壮支持来轻松地利用原先为 Ajax 应用程序创建的现有服务,比如 iTunes Search API。可以从 参考资料 部分找到该应用程序的完整源代码。

加载用户界面:Java 代码

SearchDemo 类实现 org.apache.pivot.wtk.Application 接口,该接口作为每个 Pivot 应用程序的主入口点。它定义以下 4 个方法,这些方法类似于在传统的 applet 开发中使用的生命周期方法:

  • startup():应用程序启动时调用
  • shutdown():关闭正在运行的应用程序时调用
  • suspend():临时禁用应用程序时调用
  • resume():恢复暂停的应用程序时调用

下面将讨论样例应用程序中的 startup()shutdown() 实现;这个例子中没有使用 suspend()resume()

startup()

清单 6 中定义了应用程序中的 startup() 方法。

清单 6. 应用程序的 startup() 方法
public void startup(Display display, Map<String, String> properties) 
throws Exception {
    WTKXSerializer wtkxSerializer = new WTKXSerializer();
    wtkxSerializer.put(APPLICATION_KEY, this);

    window = (Window)wtkxSerializer.readObject(this, "search_demo.wtkx");
    wtkxSerializer.bind(this, SearchDemo.class);

    ...    
    window.open(display);

    termTextInput.requestFocus();
}

该方法创建 org.apache.pivot.wtkx.WTKXSerializer 的一个用于从 WTKX 文件加载 UI 的实例。它将一个对自身的引用添加到序列化器作用域中,从而使在该文件中定义的脚本代码能够回调到应用程序,并通过在 executeQuery() 方法 小节中讨论的 executeQuery() 方法执行查询。然后,它调用序列化器的 readObject() 方法,该方法解析 WTKX 源代码并返回与根 WTKX 元素对应的类接口。

然后,startup() 在序列化器上调用 bind() 方法。这个方法将 WTKX 文件中的命名对象引用映射到应用程序的成员变量。源文件中的对象通过 wtkx:id 属性来标识,并且在 Java 源代码中使用 @WTKX 注释标记对应的成员变量(见 清单 7)。

清单 7. 使用 @WKTX 注释标记成员变量
@WTKX private TextInput termTextInput;
@WTKX private PushButton searchButton;
@WTKX private Label statusLabel;
@WTKX private TableView resultsTableView;
...

@WTKX 注释的目的仅是为开发人员提供方便。您可以通过序列化器的 get() 方法获得相同的引用;例如,startup() 方法可能包含大量类似于以下语句的语句:
termTextInput = (TextInput)wtkxSerializer.get("termTextInput");

然后,startup() 打开窗口,并要求将用户输入焦点设置为搜索词汇文本输入。

shutdown() 方法

清单 8 中定义了 shutdown() 方法。

清单 8. 应用程序的 shutdown() 方法
public boolean shutdown(boolean optional) {
    if (window != null) {
        window.close();
    }

    return false;
}

这个方法关闭 startup() 方法打开的主应用程序窗口,并返回 false 表示应该继续关闭操作(即不应该取消关闭操作。如果该方法返回 true 将执行取消关闭操作)。

接下来您将看到这在现有的服务 —— 基于 JSON 的 iTunes Search API —— 中是如何工作的:。

执行搜索查询:JSON 和 iTunes 搜索 API

iTunes Store 是 Apple 为 iTunes 媒体管理软件的用户提供的在线媒体目录。这个商店允许用户浏览和购买音乐、电影和其他数字产品。

Apple 为对 iTunes Store 执行简单的搜索查询提供一个基于 JSON 的 HTTP API。例如,获取以下 URL 的内容将返回关于 Cheap Trick 乐队的搜索结果集合:

http://ax.phobos.apple.com.edgesuite.net/WebObjects/MZStoreServices.woa/wa/itmsSearch?
limit=100&term=cheap+trick&output=json&media=all&country=us

(注意:为了格式美观以上 URL 被分为两行。它实际是一个连续的字符串)。

该查询的结果类似于 清单 9(为了保持简洁省略了一些结果)。

清单 9. 查询结果
{ "resultCount": 100,
  "results": [
    { "wrapperType": "track", 
      "mediaType": "song", 
      "artistName": "Cheap Trick", 
      "itemParentName": "Heaven Tonight (Remastered)", 
      "itemParentCensoredName": "Heaven Tonight (Remastered)", 
      "itemCensoredName": "Surrender", 
      "itemName": "Surrender", 
      "artistLinkUrl": "http://itunes.apple.com/WebObjects/MZStore.woa
/wa/viewArtist?id=461577&uo=4", 
      "artworkUrl60": "http://a1.phobos.apple.com/us/r1000/015/Music/47/5b
/a4/mzi.epawifmt.60x60-50.jpg", 
      "artworkUrl100": "http://a1.phobos.apple.com/us/r1000/015/Music/47/5b
/a4/mzi.epawifmt.100x100-75.jpg", 
      "country": "USA", 
      "currency": "USD", 
      "discCount": 1, 
      "discNumber": 1, 
      "itemExplicitness": "notExplicit", 
      "itemLinkUrl": "http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewAlbum?i
=203267147&id=203267125&s=143441&uo=4", 
      "itemPrice": "0.99000", 
      "itemParentExplicitness": "notExplicit", 
      "itemParentLinkUrl": "http://itunes.apple.com/WebObjects/MZStore.woa/wa
/viewAlbum?i=203267147&id=203267125&s=143441&uo=4", 
      "itemParentPrice": "9.99000", 
      "previewUrl": "http://a1060.phobos.apple.com/us/r1000/000/Music/4c/4c
/ab/mzi.zquuboiu.aac.p.m4p", 
      "primaryGenreName": "Rock", 
      "trackCount": 13, 
      "trackNumber": 1, 
      "trackTime": 253733},  
    ...
  ]
}

所有 iTunes 查询 URL 都以这个基 URL 开始:

http://ax.phobos.apple.com.edgesuite.net/WebObjects/MZStoreServices.woa/wa/itmsSearch

您可以通过查询字符串参数定制它们,例如:

  • limit=10:将结果数量限制为 10 个
  • term=cheap+trick:搜索与字符串 “cheap trick” 匹配的条目
  • output=json:请求使用 JSON 作为输出格式(默认的响应为 HTML 页面,主要用于构造到商品内容的链接)
  • media=all:请求匹配所有媒体类型(其他可能出现的值包括 “music”、“movie” 或 “podcast”)
  • country=us:请求结果来自美国的 iTunes Store

样例应用程序使用该 API 来获取关于 iTunes Store 的内容,并将其呈现给用户(从 参考资料 部分可以获得下载完整 API 的链接)。

要获得便于浏览响应内容(比较详细)的实用工具(用 Pivot 编写),请从 参考资料 部分获取相关链接。它要求使用 Java 6 SDK。

将查询返回的 JSON 数据粘贴到该 applet 之后,数据将以更容易导航的树视图呈现。

executeQuery() 方法

主应用程序定义一个额外的方法 executeQuery(),WTKX 文件中定义的事件处理程序调用它来执行实际的搜索。这个方法执行 HTTP 请求并处理获取的 JSON 结果。它接受包含搜索字符串的单个字符串参数。

大部分工作都由 org.apache.pivot.wtk.GetQuery 的一个实例来完成。该类表示一种 Pivot 称其为 “Web query” 的类型。Web 查询是 Pivot 用于与远程数据服务通信的原生方法。它们的主要目的是为与基于 JSON 的 REST 服务交互提供便利。不过它们是非常通用的,支持与任何基于 HTTP 的服务(不管使用什么格式)通信。Pivot 还为其他 HTTP 操作提供查询类,包括 POSTPUTDELETE

清单 10 显示了 executeQuery() 设置查询请求的方式。

清单 10. executeQuery() 方法
getQuery = new GetQuery(QUERY_HOSTNAME, BASE_QUERY_PATH);
getQuery.getParameters().put("term", term);
getQuery.getParameters().put("country", country);
getQuery.getParameters().put("media", MEDIA);
getQuery.getParameters().put("limit", Integer.toString(LIMIT));
getQuery.getParameters().put("output", "json");

然后,它更新 UI 的状态以反映搜索正在进行并执行查询(见 清单 11)。

清单 11. 更新 UI 状态
getQuery.execute(new TaskAdapter(new TaskListener() {
    ...
});

执行查询向在构造器参数中指定的服务器发送一个 HTTP GET 请求,并反序列化生成的 JSON 数据。

Web 查询是一种任务,在 Pivot 中表示为 org.apache.pivot.util.concurrent.Task 的一个实例(GetQuery 的超类)。任务的作用是简化后台操作的执行。通过一个分发器对后台线程中的任务请求进行列队和处理。任务的工作方式类似于 Ajax 编程中使用的 XMLHTTPRequest 对象,但它们不局限于服务器请求。Pivot 任务可用于实现任何类型的后台操作。

org.apache.pivot.util.concurrent.TaskListener 的一个实例被传递给 execute() 方法。该接口定义的方法在任务执行完成之后调用(见 清单 12)。

清单 12. TaskListener 定义的方法在任务执行完成之后调用
public interface TaskListener<V> {
    public void taskExecuted(Task<V> task);
    public void executeFailed(Task<V> task);
}

第一个方法在任务成功完成之后调用,第二个方法在任务未能完成时调用。

注意,实际的监听器实现包装在 org.apache.pivot.wtk.TaskAdapter 的一个实例中。因为 Pivot 中的任务并不局限于 UI 驱动的应用程序,所以可以在执行任务的线程上调用监听器方法。不过,和大部分用户界面工具箱一样,Pivot 仅支持通过单线程(称为 事件分发线程 或 EDT)与用户加密交互。TaskAdapter 确保任务回调发生在 EDT 而不是实际的后台线程上。

任务成功完成之后就可以从查询获取结果数据。返回的 JSON 数据是一个包含两个值的对象:resultsCount,返回的结果的数量;results,包含实际搜索结果的数组。在 Pivot 中 JSON 对象被转换成 org.apache.pivot.collections.HashMap 实例,并且 JSON 数组被转换成 org.apache.pivot.collections.ArrayList 实例。从根结果对象提取包含结果数据的列表,如 清单 13 所示。

清单 13. 包含结果数据的列表
Map result = (Map)task.getResult();
List results = (List)result.get("results");

在保留先前应用的排序之后,结果被设置为表视图:resultsTableView.setTableData(results);

结果可以直接作为表数据使用,因为 Pivot 的 TableView 组件使用一个 org.apache.pivot.collections.List 实例作为数据模型,并且包含 JSON 结果数据的 ArrayList 使用该接口的一个实现。Pivot 中所有数据驱动的组件,包括 ListView、TreeView 和 Spinner 都使用 Pivot 集合作为数据模型。这使得 Pivot 能够高效地使用基于 JSON 的 Web 服务提供的数据,因为在使用从服务器返回的数据填充 UI 之前,不需要转换或调整它们。


事件处理:JavaScript

至此,您已经了解了搜索结果数据的结果以及演示应用程序如何处理它们,但您还没有看到查询是如何发起的。在这个小节中,您将了解如何使用 JavaScript 实现该目的。

发起查询

与大部分其他用户界面工具箱一样,Pivot 应用程序中的操作一般都是为响应事件 而发生的。事件是发生事情时发出的通知。它们通常是由用户输入触发的,比如单击鼠标或键盘按键,但其他异步进程也可以触发事件(比如成功执行查询任务,见 executeQuery() 方法 小节)。

调用方通过注册事件监听器表示它们关注事件。在 Pivot 中,事件监听器被定义为定义事件的接口的实现。例如,以下接口为按钮定义一个 “pressed” 事件(见 清单 14)。

清单 14. 按钮的 Pressed 事件
public interface ButtonPressListener {
    public void buttonPressed(Button button);
}

在 Java 代码中,通过向相关的 “监听器列表” 添加事件监听器来注册它们(见 清单 15)。

清单 15. 注册事件监听器
myButton.getButtonPressListeners().add(new ButtonPressListener() {
    public void buttonPressed(Button button) {
        // Handle event
    }
});

这看起来非常简单,但它也可以变得很复杂,因为许多监听器接口定义了多个方法。尽管包含的适配器类为大部分监听器接口提供了默认的 no-op 实现,但所有重要的应用程序都需要定义多个事件监听器。将所有事件监听器创建为匿名(甚至命名)内部类导致应用程序的 Java 代码变得复杂,并模糊了类的原始目的。幸运的是,Pivot 为定义监听器提供一种更加简单的方法:WTKX 脚本块。

例如,考虑一下 清单 16 中的 Preview 按钮的 WTKX 声明。

清单 16. preview 按钮的 WTKX 声明
<PushButton wtkx:id="previewButton" buttonData="Preview" enabled="false">
    <buttonPressListeners>
        <wtkx:script>
        <![CDATA[
        importPackage(org.apache.pivot.wtk);
        function buttonPressed(button) {
            var selectedResult = resultsTableView.getSelectedRow();
            ApplicationContext.open(selectedResult.get("previewUrl"));
        }
        ]]>
        </wtkx:script>
    </buttonPressListeners>
</PushButton>

这个标记创建 org.apache.pivot.wtk.PushButton 的一个实例,并将 <wtkx:script> 元素的内容注册为一个按钮监听器。在该脚本元素中定义的函数与监听器接口声明的方法对应。定义额外处理程序是可选的,尽管在这个例子中不是很明显;如果调用方对特定事件不感兴趣,那么可以省略针对该事件的处理程序。结果是,在脚本中实现事件监听器比在 Java 环境中实现更加紧凑简洁。


结束语

在本教程中,您清楚地看到 Pivot 的理念 “选择正确的工具”:

  • XML,具有层次结构的标记语言,它使可视化输出变得更加容易,常用于声明用户界面的结构。
  • Java,流行的健壮编程语言,用于在应用程序中定义主要行为。
  • JavaScript,著名并被广泛使用的脚本语言,用于定义更快的事件处理逻辑,这些逻辑在 Java 环境常常更加繁杂

本教程介绍了 Apache Pivot,以及如何使用它为 iTunes Store 构建一个简单的搜索客户端。此外,还介绍了 WTKX 标记语言,概述了如何在 Pivot 中使用 Java 和 JSON,并展示了一些使用脚本代码处理事件的例子。

参考资料

学习

  • 您可以参阅本文在 developerWorks 全球网站上的 英文原文
  • Apache Pivot:访问该站点更多地了解关于 Pivot 和 WTKX 的信息。
  • 来自 Apache.org 的 WTKX Primer:了解 WTKX,它是用于构建 Pivot 应用程序的、基于 XML 的标记语言。
  • Apache Pivot FAQ:获得常见问题的解答。
  • Demos section:在 Pivot Web 站点上找到其他 Pivot 演示并阅读 Pivot 教程
  • Pivot iTunes Search Demo:查看实际运行中的示例应用程序。
  • Stock Tracker tutorial example:试用这个样例 Pivot 应用程序,它使用 Web 查询处理 Yahoo! Finance 股票行情 Web 服务返回的 CSV 数据。
  • JSON:了解所有关于轻量级数据交换格式的信息。
  • TIOBE Programming Community index:了解编程语言流行的原因。
  • XML 新手入门:在 developerWorks 上访问这个入门站点,它为 XML 开发人员提供出色的参考资料。
  • XML 专区:访问 developerWorks XML 专区,获得广泛的技术文章和技巧、教程和标准。
  • 查看免费的 演示中心 体验并了解 IBM 和开放源码技术及产品功能。
  • 查阅最近将在全球举办的面向 IBM 开放源码开发人员的研讨会、交易展览、网络广播和其他 开放源码活动
  • 开放源码专区:访问 developerWorks 开放源码专区,获得丰富的 how-to 信息、工具和项目更新,帮助您用开放源码技术进行开发,并与 IBM 产品结合使用。
  • developerWorks developerWorks Java 技术专区:找到关于 Java 编程的各个方面的文章。
  • IBM XML 认证:了解如何才能成为一名 IBM 认证的 XML 和相关技术的开发人员。
  • XML 技术库:访问 developerWorks XML 专区,获得广泛的技术文章和技巧、教程、标准和 IBM 红皮书。
  • developerWorks 技术活动网络广播:随时关注技术的最新进展。
  • developerWorks 播客:收听针对软件开发人员的有趣访谈和讨论。

获得产品和技术

讨论

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=XML, Open source, Web development
ArticleID=449799
ArticleTitle=使用 Apache Pivot 构建 iTunes 搜索客户端
publish-date=11262009