级别: 中级 Yury Kats (ykats@us.ibm.com), 顾问软件工程师, IBM, Intel, Microsoft,HP
2007 年 4 月 02 日 预输入字段(type-ahead input fields,或者叫做“输入提示”或“自动完成”)正在 Web 上流行起来。它需要猜测用户的输入,并为用户提供可供选择的提示。Rational Application Developer version 7.0 提供了 JSF 组件和 AJAX 功能,这样就使得这一过程变得更迅速更容易。本文解释了 Rational Application Developer V7 所支持的预输入字段,并帮助您理解如何创建两类预输入字段的过程--一类是用本地数据源来产生提示,另一类是用公开的 Web 服务。
预输入是如何工作的
预输入字段的目的就是改善用户体验。当有人在一个页面的一个输入字段输入内容时,计算机经常会猜测用户要输入什么内容,然后为用户完成数据输入。
例如,如果用户需要输入所在州的名称,输入了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 项目:
- 从菜单中选择 File > New > Project > Dynamic Web Project。(参见 图 1。)
- 在New Project向导中:
- 输入
project name。
- 选择 Faces Project 配置。
- 选择 Add project to an EAR。
- 点击 Finish。
图 1. New Dynamic Web Project 截屏
创建 Web 页面
为创建 Web 页面:
- 在Project Explorer中右击project name 。
- 从列表中选择 New > Web Page 。
- 在 New Web Page 向导中,
输入页面名称。(参见 图 2。)
- 点击 Finish。
图 2. New Web Page 显示
创建一个输入控件
将 Enhanced Faces Components工具板的Input 组件拖入页面中。(参见 图 3。)
图 3. 增加输入控件
增加预输入的快速简易步骤
既然您已经有了一个输入栏,您可以按照如下步骤实现预输入特性(参见 图 4):
- 点击选择 Input栏。
- Properties 视图更新显示了
inputText 标签的属性。 将inputText 标签变为Behavior 页面。
- 选择 Enable typeahead option。
以上就是您所要做的!
图 4. 实现预输入特性
注意,Input 组件的显示表示它支持预输入功能,Properties 视图变为显示预输入属性。(参见图 5。)
图 5. 所实现的预输入属性
既然您已经实现了支持预输入字段的输入栏,剩下的就是要处理服务器代码以产生推荐列表。
产生推荐的方式
处理用户的输入并产生推荐列表示预输入功能的目标。这就是您增加预输入特性所要实现的。
为了要预输入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):
- 输入类名(例如,
Suggestions)。
- 选择 java.util.AbstractMap 作为超类。
- 选择 Create inherited abstract methods。
- 点击 Finish。
图 6. New class
作为受管 bean 添加这个 bean:
- 切换回到 Web 页面 (page1.jsp)。
- 在 Page Data View中, 右击 Faces Managed Beans 类别, 选择New > Faces Managed Bean。(参见 图 7。)
- 在 Add Bean 对话框中:
- 输入
bean name。
- 输入
bean class。
- 选择 session scope。
- 点击 Finish。
图 7. 新建 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. 预输入值集合
既然您已经保存了所有的文件并在服务器端运行了page1.jsp。当打开了浏览器窗口时,您会看到一个输入栏。 (参见图 9。)只要用户开始输入,就会在输入栏下打开一个推荐列表框。它包括了10个选项,每个选项包括了输入栏的当前值加上一个从0至9的数字。
图 9. 运行
本例中所获得的推荐并不十分有用,因为我们有意将 bean 代码做的简洁以证明预输入组件如何工作。在实际应用中,您能够执行更复杂的查询并和数据库匹配,例如雇员列表(如果用户输入一个名字)或者产品列表(如果用户在类别中搜索)。 如果数据集比较小,您还可以不断加强它,例如美国的州列表。或者,您可以使用 Web 服务从一家独立提供商获取推荐列表。
来自 Web 服务的推荐生成
Web 服务也许是最普遍的预输入来源。当您使用Web服务时,您不需要知道或担心数据来源或者逻辑是如何实现的。get方式的实现就如同调用Web服务并返回ArrayList结果一样简单。
有各种不同的Web服务类型供您使用。您可以创建属于您自己的Web服务(这部分内容超出了本文的范围),您可以使用您企业的其他Web服务,或者您可以使用公开的Web服务。在互联网上有许多开放式的Web服务。本例将使用 Aonaware的字典查询服务。这一服务可以返回以某前缀开始的英语单词列表,如果您想帮助用户正确输入英文单词,这一功能将非常适合于预输入功能。
为保证您的程序能够使用这一Web服务,您需要为 Rational Application Developer IDE 添加这一服务,以便于能够产生所有必需的Web服务类。之后,您需要在 Suggestions 类中改变get方法以使用这一服务。
添加加Web服务以产生推荐
请按如下步骤给您的项目添加 Web服务:
- 返回 Web 页面 (page1.jsp)。
- 在 Page Data View中,右击 Services 类别,选择 New > Web Service。(参见 图 10。)
- 在 Web Services Discovery 对话框中:
- 选择 Web Services from a known URL。
- 为Web服务输入 URL地址:
http://services.aonaware.com/DictService/DictService.asmx?wsdl,之后点击 Go。
- 当 Web 服务出现在 Information 框中,点击 Add to Project。
- 在 Add Web Service对话框中,选择任意方法,之后点击 Finish。
图 10. 添加Web服务
使用 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");
|-------10--------20--------30--------40--------50--------60--------70--------80--------9|
|-------- XML error: The previous line is longer than the max of 90 characters ---------|
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行,激活服务并将当前输入栏的值作为参数传递。其他两个参数(
wn 和 prefix)定义了使用哪一词典、应用哪种匹配规则。
- 25-28行,将由服务器返回的结果变换为预输入组件可以理解的 ArrayList 类型。
现在您需要保存所有文件并在服务器端运行 page1.jsp。(参见 图 11。)这时,如果您输入一个或两个字母,不会显示出任何东西。但是如果输入三个以上字母,将会显示出来自于词典的包含10个单词的推荐框。
图 11. 运行
如何定制您的预输入组件
您可以使用这些属性定制预输入行为:
| maxSuggestions | 推荐所显示的最大数量。缺省情况为10。 | | startCharacters | 显示推荐框的最小字符数。缺省情况为1。 | | startDelay | 推荐前延迟的毫秒数。缺省情况为500。 | | matchWidth | 如果为真,推荐列表与输入栏同宽。如果为假,宽度由列表的CSS决定。 | | size | 推荐列表的高度(每行)。如果所推荐的内容多于显示的行数, 将会在推荐列表中显示滚动条。缺省情况为10。 | | type |
suggest或 autocomplete 指明了是否在下拉列表中显示推荐内容(用户从列表中选择),或是自动选择列表中的第一项(本例中,用户可通过箭头选择不同推荐)。缺省情况为 suggest。 | | onstart | 当AJAX请求被提交时所执行的JavaScript函数。 | | oncomplete | 当AJAX请求被处理时所执行的JavaScript函数。 |
注意:例如,您可以使用 onstart和oncomplete 来给用户提供服务正在获取推荐的可视化反馈。
由以下CSS类控制推荐列表框的表示:
| <base> | 类的名称可由预输入组件的styleClass属性设置。缺省情况是 inputText_Typeahead。
制定包含列表的 div风格。 | | <base>-List | 制定显示推荐列表窗口的风格。 | | <base>-Item | 制定列表中的条目风格。 | | <base>-Item-Selected | 制定当前所选项的风格。 |
注意
预输入组件如同其他使用AJAX的组件一样,具有产生大量网络阻塞的危险。当考虑为您的Web程序使用这一组件时,不要忘记每次按键时都会产生额外的请求。如果为大量用户服务,则服务器将要处理大量的请求。
为减少请求的数量,最好将startDelay 和 startCharacters 属性设为较高值,以便于浏览器在一定延迟后发送AJAX请求--或者在用户输入一些字符后,或者在用户停顿后。
参考资料 学习
获得产品和技术
讨论
关于作者  | 
|  | Yury Kats 是一名IBM Rational Application Developer 团队的开发成员,他的工作主要是JSF实现、组件和工具安装。 |
对本文的评价
|