在 Rational Application Developer V7 中利用JSF、AJAX 和Web 服务提高带有预输入字段的 Web 应用程序的可用性

预输入字段(type-ahead input fields,或者叫做“输入提示”或“自动完成”)正在 Web 上流行起来。它需要猜测用户的输入,并为用户提供可供选择的提示。Rational Application Developer version 7.0 提供了 JSF 组件和 AJAX 功能,这样就使得这一过程变得更迅速更容易。本文解释了 Rational Application Developer V7 所支持的预输入字段,并帮助您理解如何创建两类预输入字段的过程--一类是用本地数据源来产生提示,另一类是用公开的 Web 服务。

Yury Kats (ykats@us.ibm.com), 顾问软件工程师, IBM

Yury Kats photoYury Kats 是 IBM Rational Application Developer 团队的一名开发成员,主要从事于 JSF 实现,组件以及工具的开发。



2007 年 4 月 02 日

预输入是如何工作的

预输入字段的目的就是改善用户体验。当有人在一个页面的一个输入字段输入内容时,计算机经常会猜测用户要输入什么内容,然后为用户完成数据输入。

例如,如果用户需要输入所在州的名称,输入了Mass,很可能会输入 Massachusetts。这时,计算机可以自动在Mass后增加achusetts。这样可以节省时间并且减少出现潜在错误的机会,因为这样用户很少出现拼写错误。

虽然常常能够正确的猜测出用户要输入的内容,但也会出现错误。 万一用户只想输入Ma,而不是Mass呢?有三个州是以Ma开头的;因此,不可能预测出用户要输入哪一个州。在这种情况下,就会为她提供一个选择列表:Maine,Maryland 和 Massachusetts。这些选择经常会在输入字段下的一个列表框中显示出来。当她选择了其中的一个后,就会在输入栏显示出来,完成输入。但是,随着她的输入,所建议的数量会不断减少,因为用户输入的越多,计算机软件就会猜测的越准。

在Web浏览器中实现这一技术是非常简单的,但是到现在为止并没有被广泛采用。如果Web浏览器要获得推荐列表,它需要在用户不知道的情况下连接服务器。这种浏览器与服务器间的后台连接一般被称为AJAX(一种异步 JavaScript™ 和 XML 的缩写),这种技术在Web站点中正变得越来越流行。Google Suggest 可能是最有名的实例。

预输入字段的想法非常简单:只要用户在输入栏输入一个字符,浏览器就会通过传输当前参数内容,利用AJAX与服务器连接。 服务器用以评估内容,并给浏览器返回推荐列表。之后,浏览器通过输入栏显示列表框以提供推荐内容。如果用户选择了其中的一个推荐,就会在输入栏内显示。

实现这一服务主要有四部分:

  • 浏览器使用JavaScript用以创建 AJAX,在后台连接服务器。
  • 当从服务器接收到推荐列表时,浏览器还需要使用 JavaScript 定义如何表示列表。
  • 服务器需要代码以接收来自浏览器的AJAX 请求,并给予应答。
  • 服务器还需要猜测用户将要输入及所推荐的代码。

虽然这一想法十分简单, 但是实现所有部分将是十分复杂的。幸运的是, Rational Application Developer V7中的JavaServer™ Faces (JSF) 库实现了前三部分,可以帮助您写入客户端的JavaScript和客户/服务器AJAX通信。在您为页面加入预输入JSF组件后,您需要提供服务器端代码以产生推荐(第四部要求)。您能从本文中学到两种方式:使用本地数据源或者使用Web服务的代码。


初始设置

首先, 您需要建立一个 Web 项目,Web 页面和一个输入控件。

建立 Web 项目

为创建一个Web 项目:

  1. 从菜单中选择 File > New > Project > Dynamic Web Project。(参见 图 1。)
  2. 在New Project向导中:
    1. 输入project name
    2. 选择 Faces Project 配置。
    3. 选择 Add project to an EAR
  3. 点击 Finish
图 1. New Dynamic Web Project 截屏
Figure 1. Dynamic Web Project screen

创建 Web 页面

为创建 Web 页面:

  • Project Explorer中右击project name
  • 从列表中选择 New > Web Page
  • New Web Page 向导中,输入页面名称。(参见 图 2。)
  • 点击 Finish
图 2. New Web Page 显示
Figure 2. Web Page display

创建一个输入控件

Enhanced Faces Components工具板的Input 组件拖入页面中。(参见 图 3。)

图 3. 增加输入控件
Figure 3. input control

增加预输入的快速简易步骤

既然您已经有了一个输入栏,您可以按照如下步骤实现预输入特性(参见 图 4):

  1. 点击选择 Input栏。
  2. Properties 视图更新显示了 inputText 标签的属性。 将inputText 标签变为Behavior 页面。
  3. 选择 Enable typeahead option

以上就是您所要做的!

图 4. 实现预输入特性
Enabling type-ahead

注意,Input 组件的显示表示它支持预输入功能,Properties 视图变为显示预输入属性。(参见图 5。)

图 5. 所实现的预输入属性
Type-ahead enabled

既然您已经实现了支持预输入字段的输入栏,剩下的就是要处理服务器代码以产生推荐列表。


产生推荐的方式

处理用户的输入并产生推荐列表示预输入功能的目标。这就是您增加预输入特性所要实现的。

为了要预输入JSF 组件工作,它的 value 属性必须关联 Map 对象。当客户端需要来自服务器的推荐时,它会调用 Map 的 get 方法,并将当前输入栏内容能够作为参数传递。Get 方法能够产生推荐列表并在 ArrayList对象中返回给客户端。

在 JSF 中,这表示您需要创建一个实现 java.util.Map 接口的受管的 bean,并且增加代码为get方式产生推荐。您能够将这一受管的 bean 放入会话或应用范围,以便它只需被创建一次。

在受管 bean 中的生成建议

为了创建新的 bean:

  • Project Explorer中右击项目的 Java Resources文件夹。
  • 从列表中选择 New > Package
  • 输入库名称(例如, beans), 点击Finish
  • Project Explorer中右击 package name
  • 从上下文菜单中选择 New > Class
  • New Class 向导中(参见图 6):
    1. 输入类名(例如, Suggestions)。
    2. 选择 java.util.AbstractMap 作为超类。
    3. 选择 Create inherited abstract methods
  • 点击 Finish
图 6. New class
New class display

作为受管 bean 添加这个 bean:

  1. 切换回到 Web 页面 (page1.jsp)。
  2. Page Data View中, 右击 Faces Managed Beans 类别, 选择New > Faces Managed Bean。(参见 图 7。)
  3. Add Bean 对话框中:
    1. 输入bean name
    2. 输入 bean class
    3. 选择 session scope
  4. 点击 Finish
图 7. 新建 managed bean
managed bean

既然您已经创建了 bean, 您需要实现它的 get 方法。为了做到简单,您需要建立一个包含10个推荐的列表。整个 bean 看起来想这样:

清单 1. Suggestions bean
package beans;

import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Set;

public class Suggestions extends AbstractMap {

    public Object get(Object key) {
        ArrayList suggestions = new ArrayList(10);
        String currentValue = key.toString();
        for(int i = 0; i < 10; i++) {
            suggestions.add(currentValue + " " + i);
        }
        return suggestions;
    }

    public Set entrySet() {
        return null;
    }
}

您的 bean 和输入组件已就绪了。您只需要将它们绑定在一起:

  • 返回 Web 页面 (page1.jsp)。
  • 选择 type-ahead component
  • 切换回到 Properties 视图。(参见 图 8。)
  • Value 栏中输入name of the managed bean#{suggestions}
图 8. 预输入值集合
type-ahead value set

既然您已经保存了所有的文件并在服务器端运行了page1.jsp。当打开了浏览器窗口时,您会看到一个输入栏。 (参见图 9。)只要用户开始输入,就会在输入栏下打开一个推荐列表框。它包括了10个选项,每个选项包括了输入栏的当前值加上一个从0至9的数字。

图 9. 运行
Run on server

本例中所获得的推荐并不十分有用,因为我们有意将 bean 代码做的简洁以证明预输入组件如何工作。在实际应用中,您能够执行更复杂的查询并和数据库匹配,例如雇员列表(如果用户输入一个名字)或者产品列表(如果用户在类别中搜索)。 如果数据集比较小,您还可以不断加强它,例如美国的州列表。或者,您可以使用 Web 服务从一家独立提供商获取推荐列表。

来自 Web 服务的推荐生成

Web 服务也许是最普遍的预输入来源。当您使用Web服务时,您不需要知道或担心数据来源或者逻辑是如何实现的。get方式的实现就如同调用Web服务并返回ArrayList结果一样简单。

有各种不同的Web服务类型供您使用。您可以创建属于您自己的Web服务(这部分内容超出了本文的范围),您可以使用您企业的其他Web服务,或者您可以使用公开的Web服务。在互联网上有许多开放式的Web服务。本例将使用 Aonaware的字典查询服务。这一服务可以返回以某前缀开始的英语单词列表,如果您想帮助用户正确输入英文单词,这一功能将非常适合于预输入功能。

为保证您的程序能够使用这一Web服务,您需要为 Rational Application Developer IDE 添加这一服务,以便于能够产生所有必需的Web服务类。之后,您需要在 Suggestions 类中改变get方法以使用这一服务。

添加加Web服务以产生推荐

请按如下步骤给您的项目添加 Web服务:

  1. 返回 Web 页面 (page1.jsp)。
  2. Page Data View中,右击 Services 类别,选择 New > Web Service。(参见 图 10。)
  3. Web Services Discovery 对话框中:
    1. 选择 Web Services from a known URL。
    2. 为Web服务输入 URL地址: http://services.aonaware.com/DictService/DictService.asmx?wsdl,之后点击 Go
    3. 当 Web 服务出现在 Information 框中,点击 Add to Project
  4. Add Web Service对话框中,选择任意方法,之后点击 Finish
图 10. 添加Web服务
Web service

使用 Web 服务

在为项目添加了Web服务后,Rational Application Developer IDE 产生所有应用服务的代码。现在您可以返回到 Suggestions 类,并且修改get 方法以激活服务,从而不必得到10条没用的字符串。

Suggestions bean 的代码如下:

清单 2. Web 服务的 Suggestions bean
01 package beans;
02
03 import java.util.AbstractMap;
04 import java.util.ArrayList;
05 import java.util.Set;
06 import com.aonaware.services.DictServiceSoapProxy;
07 import com.aonaware.services.DictionaryWord;
08
09 public class Suggestions extends AbstractMap {
10
11    DictServiceSoapProxy proxy = null;
12
13    public Suggestions() {
14        proxy = new DictServiceSoapProxy();
15    }
16
17    public Object get(Object key) {
18        String currentValue = key.toString();
19        if(currentValue.length() < 3) {
20            return null;
21        }
22        ArrayList result = new ArrayList();
23        try {
24            DictionaryWord[] words = proxy.matchInDict("wn", currentValue, "prefix");
25            for(int i = 0; i < words.length; i++) {
26                String word = words[i].getWord();
27                result.add(word);
28            }
29        } catch (Exception e) {
30        }
31        return result;
32    }
33
34    public Set entrySet() {
35        return null;
36    }
37 }

以下是对于代码主要部分的简要分析:

  • 11行,声明了一个代理变量以激活服务。(DictServiceSoapProxy类是添加这一服务时 Rational Application Developer 软件多产生的类之一)。
  • 14行,创建了一个 Web 服务代理实例。
  • 19-21行,保证了所要传递的字符串不会太短。这样避免服务器响应过于庞大的请求。(想象一下要返回所有以A开始的单词的情况!)
  • 24行,激活服务并将当前输入栏的值作为参数传递。其他两个参数(wnprefix)定义了使用哪一词典、应用哪种匹配规则。
  • 25-28行,将由服务器返回的结果变换为预输入组件可以理解的 ArrayList 类型。

现在您需要保存所有文件并在服务器端运行 page1.jsp。(参见 图 11。)这时,如果您输入一个或两个字母,不会显示出任何东西。但是如果输入三个以上字母,将会显示出来自于词典的包含10个单词的推荐框。

图 11. 运行
Run on server

如何定制您的预输入组件

您可以使用这些属性定制预输入行为:

maxSuggestions推荐所显示的最大数量。缺省情况为10。
startCharacters显示推荐框的最小字符数。缺省情况为1。
startDelay推荐前延迟的毫秒数。缺省情况为500。
matchWidth如果为真,推荐列表与输入栏同宽。如果为假,宽度由列表的CSS决定。
size推荐列表的高度(每行)。如果所推荐的内容多于显示的行数, 将会在推荐列表中显示滚动条。缺省情况为10。
typesuggestautocomplete 指明了是否在下拉列表中显示推荐内容(用户从列表中选择),或是自动选择列表中的第一项(本例中,用户可通过箭头选择不同推荐)。缺省情况为 suggest
onstart当AJAX请求被提交时所执行的JavaScript函数。
oncomplete当AJAX请求被处理时所执行的JavaScript函数。

注意:例如,您可以使用 onstartoncomplete 来给用户提供服务正在获取推荐的可视化反馈。

由以下CSS类控制推荐列表框的表示:

<base>类的名称可由预输入组件的styleClass属性设置。缺省情况是 inputText_Typeahead
制定包含列表的 div风格。
<base>-List制定显示推荐列表窗口的风格。
<base>-Item制定列表中的条目风格。
<base>-Item-Selected制定当前所选项的风格。

注意

预输入组件如同其他使用AJAX的组件一样,具有产生大量网络阻塞的危险。当考虑为您的Web程序使用这一组件时,不要忘记每次按键时都会产生额外的请求。如果为大量用户服务,则服务器将要处理大量的请求。

为减少请求的数量,最好将startDelaystartCharacters 属性设为较高值,以便于浏览器在一定延迟后发送AJAX请求--或者在用户输入一些字符后,或者在用户停顿后。

参考资料

学习

获得产品和技术

讨论

条评论

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=Rational, Web development
ArticleID=206274
ArticleTitle=在 Rational Application Developer V7 中利用JSF、AJAX 和Web 服务提高带有预输入字段的 Web 应用程序的可用性
publish-date=04022007