源自:http://www.netbeans.org/kb/55/vwp-ajaxprogressbar_zh_CN.html)
使用 AJAX 进度栏组件
2007 年 5 月 [修订号:V5.5.1-1] |
本教程介绍了如何使用 NetBeans Visual Web Pack 5.5 构建一个使用样例 Java BluePrints AJAX 进度栏组件的 Web 应用程序。此外,本教程还介绍了一些进度栏的应用实例。首先,您需要为可以确定任务进度的用例配置进度栏。在这种情况下,进度栏将通过百分比来显示任务的完成进度。接下来,您需要为任务进度不确定的用例配置进度栏。对于这种情况,进度栏并不使用百分比来表示任务的完成进度,而只表示某项任务正在进行当中,这是因为此任务的进度情况是未知的。最后,您需要配置一个用于处理失败任务的进度栏。 |
目录
|
本教程中使用的外部代码
|
-
pb.js
|
本教程将使用以下技术和资源
JavaServer Faces 组件/ Java EE 平台 | 1.2/Java EE 5* 1.1/J2EE 1.4 | |||
Travel 数据库 | 不是必需的 | |||
BluePrints AJAX 组件库 | 必需 |
* 该教程发布时,只有 Sun Java System Application Server 支持 Java EE 5。
本教程是针对使用 Sun Java Application Server PE 9.0 Update Release 1 和 Tomcat 5.5.17 进行定制的。如果您使用的是其他服务器,请参考发行说明和常见问题解答以了解已知问题和解决方法。有关支持的服务器和 Java EE 平台的详细信息,请参见发行说明。
设置应用程序
SimpleTask.java
和
pb.js
。
SimpleTask.java
将模拟一个在单独线程中执行的服务器端任务。无论用户何时启动(或重新启动)此任务,
SimpleTask.java
中的
start
方法都会产生一个新的线程,该线程或者休眠,或者递增计数器的值。
pb.js
文件包含了一些函数,供应用程序中与 JavaScript 相关的组件属性调用。这些属性包括进度栏的
onComplete
和
onFail
属性、按钮的
onClick
属性和表单的
onSubmit
属性。
- 下载并导入最新版本的 AJAX 组件(如果您尚未执行此操作)。
- 下载
SimpleTask.java
和pb.js
并将它们保存到您的文件系统中。 -
创建一个新的 Visual Web 应用程序项目,并将其命名为
ProgressBarExample
。将在可视设计器中打开 ProgressBarExample 的初始页。 -
按照以下操作,将
SimpleTask.java
添加到项目中:- 从主菜单中,选择“文件”>“添加现有项”>“Java 源代码”。导航至您保存
SimpleTask.java
所在的目录。选择该文件,然后单击“添加”。 -
在“项目”窗口中,展开“源包”> "progressbarexample"。双击 "SimpleTask.java" 节点以便在 Java 编辑器中打开该文件。
在文件顶部添加以下 package 语句:
package progressbarexample;
- 从主菜单中,选择“文件”>“添加现有项”>“Java 源代码”。导航至您保存
-
按照以下操作,将
pb.js
JavaScript 文件添加到项目中:- 选择“文件”>“添加现有项”>“其他(所有文件)”。导航并选择
pb.js
,然后单击“添加”。 - 在“项目”窗口中,将
pb.js
从“源包”> "progressbarexample" 拖到“Web 页”> "resources" 中。
- 选择“文件”>“添加现有项”>“其他(所有文件)”。导航并选择
修改会话 Bean
- 在可视设计器中打开 Page1。
-
在“概要”窗口中,右键单击 "SessionBean1",然后选择“添加”>“属性”。注意:如果在首次打开弹出式菜单时未激活“添加”菜单,请关闭该菜单,然后重新右键单击 "SessionBean1" 节点以激活“添加”子菜单。
-
对于出现的“新建属性模式”对话框,在“名称”字段中键入
taskMap
,在“类型”字段中键入HashMap
(请注意“名称”和“类型”字段是区分大小写的),并将“模式”设置为只读
,如下图所示。单击“确定”。图 1:“新建属性模式”对话框 -
右键单击 "SessionBean1" 节点,然后从弹出式菜单中选择“编辑 Java 源代码”。代码中出现的错误标注表明未找到 HashMap 类。
-
在
SessionBean1.java
中的任意位置单击鼠标右键,然后从弹出式菜单中选择“修复导入”以自动添加下列 import 语句:import java.util.HashMap;
-
将下面以粗体显示的代码行附加到
SessionBean1.init
方法的结尾处。代码样例 1:SessionBean1 属性 public void init() { // 执行从超类继承的初始化 super.init(); // 执行必须在初始化受管组件 // *之前*完成的应用程序初始化 // 待做事项 - 在此处添加您自己的初始化代码 Creator 管理的组件初始化 // 执行必须在初始化受管组件 // *之后*完成的应用程序初始化 // 待做事项 - 在此处添加您自己的初始化代码 taskMap = new HashMap(); taskMap.put("progressBar1", new SimpleTask("progressBar1", 241, 100, false)); }
此代码通过构造 HashMap 并将一个新的 SimpleTask 实例添加到 HashMap 中来填充taskMap
属性。
创建一个任务进度确定的进度栏
如果您可以确定完成任务的百分比进度,则使用任务进度确定的进度栏。在本部分,您将设计一个包含任务进度确定的进度栏和两个按钮的页面。第一个按钮用于启动、暂停和重新启动与进度栏相关的任务,第二个按钮用于停止该任务。下图显示了页面的外观:
图 2:进度页的设计 |
-
在“项目”窗口中,右键单击 "ProgressBarExample" >“组件库”节点,然后从弹出式菜单中选择“添加组件库”。选择 "BluePrints AJAX Components",然后单击“添加组件库”。IDE 会将该组件库复制到项目中,并在组件面板中添加这些组件。
- 在可视设计器中打开 Page1。
-
打开组件面板的 "BluePrints AJAX Components" 类别,然后将一个进度栏组件拖动到页面上。在本教程中,将使用
progressBar1
的缺省id
属性。注意:进度栏应如上图 2 所示。如果进度栏组件显示不正确,请在可视设计器中单击鼠标右键,然后从弹出式菜单中选择“刷新”。 - 将一个网格面板组件从组件面板的“布局”类别拖动到进度栏组件的右侧。
- 将网格面板的
id
属性设置为controlPanel
,并将columns
属性设置为2
。 -
将两个按钮组件从组件面板的“基本”类别拖动到网格面板上。请确保在放置按钮组件时,网格面板组件的外框呈蓝色实线。
-
为第一个按钮设置以下属性:
属性 值 id
variableControl
text
Start
onClick
handleVariableControlOnClick(this, 'form1:progressBar1', false)
当用户单击按钮时,handleVariableControlOnClick
函数将调用 JavaScript 来启动、暂停或重新启动进度栏。 -
为第二个按钮设置以下属性:
属性 值 id
stopControl
text
取消
onClick
handleStopControlOnClick('form1:variableControl', 'form1:progressBar1')
handleStopControlOnClick
函数将调用 JavaScript 来停止进度栏。 -
在“概要”窗口中,选择 "form1"。在“属性”窗口中,将表单的
onSubmit
属性设置为return handleFormOnSubmit()
。此 JavaScript 函数会在用户单击其中任一按钮时阻止提交页面。 -
将一个脚本组件从组件面板的“高级”类别拖动到页面上。 “概要”窗口将在 "Page1" 部分显示 "script1"。此非可视组件用于在呈现的 HTML 标记中声明 script 元素。
- 在“属性”窗口中,将脚本组件的
url
属性设置为/resources/pb.js
。请注意,此属性需要一个前导的正斜杠 (/
)。为进度栏添加代码
在本部分,您将为项目的 Java 源代码添加四个方法。这些方法用于执行以下操作并成为进度栏组件的“事件”属性:
- 启动或重新启动 AJAX 请求中指示的任务
- 暂停 AJAX 请求中指示的任务
- 停止 AJAX 请求中指示的任务
- 提取发送 AJAX 请求的进度栏的组件
id
(例如,progressBar1)
-
在 Java 编辑器中打开 Page1,然后在
destroy()
方法后添加下面以粗体显示的代码。代码样例 2:其他进度栏方法 public void destroy() { } /** * Start or resume the task indicated in the Ajax request. */ public void startOrResumeTask(FacesContext context) { String taskId = getTaskIdFromAJAXRequest(context); SimpleTask task = (SimpleTask)getSessionBean1().getTaskMap().get(taskId); Map paramMap = context.getExternalContext().getRequestParameterMap(); String doomed = (String)paramMap.get("doomed"); task.start(Boolean.parseBoolean(doomed)); } /** * Pause the task indicated in the Ajax request. */ public void pauseTask(FacesContext context) { String taskId = getTaskIdFromAJAXRequest(context); SimpleTask task = (SimpleTask)getSessionBean1().getTaskMap().get(taskId); task.pause(); } /** * Stop the task indicated in the Ajax request. */ public void stopTask(FacesContext context) { String taskId = getTaskIdFromAJAXRequest(context); SimpleTask task = (SimpleTask)getSessionBean1().getTaskMap().get(taskId); task.cancel(); } /** * Extract the component id (for instance, "progressBar1") of the * progress bar that sent the Ajax request. */ private String getTaskIdFromAJAXRequest(FacesContext context) { Map paramMap = context.getExternalContext().getRequestParameterMap(); String progressBarClientId = (String)paramMap.get("bpui_progressbar_clientId"); if (progressBarClientId == null) { throw new NullPointerException(); } //get portion from last colon forward int lastColon = progressBarClientId.lastIndexOf(NamingContainer.SEPARATOR_CHAR); if (lastColon == -1) { return progressBarClientId; } String taskId = progressBarClientId.substring(lastColon + 1); return taskId; }
在进度栏向服务器发送 AJAX 请求时,它会将其客户端 id 包含在bpui_progressbar_clientId
请求参数中。用于启动、暂停、重新启动或停止任务的 AJAX 请求将调用应用程序页面 Bean 中的startOrResumeTask
、pauseTask
或stopTask
方法。这些方法会调用getTaskIdFromAJAXRequest
方法,该方法将提取bpui_progressbar_clientId
请求参数中的组件id
(如progressBar1
)。这些方法使用组件id
来检索taskMap
中的 SimpleTask 实例,然后调用此任务的start
、pause
或cancel
方法。 -
在 Page1 的源代码中单击鼠标右键,然后从弹出式菜单中选择“修复导入”。
IDE 将添加以下 import 语句来修复“找不到类”错误:
import java.util.Map;
import javax.faces.component.NamingContainer;
import javax.faces.context.FacesContext; -
返回至 Page1 的“设计”视图,然后在进度栏组件上设置以下属性:
属性 值 stopOperation
stopTask()
resumeOperation
startOrResumeTask()
startOperation
startOrResumeTask()
pauseOperation
pauseTask()
onComplete
function() {handleProgressBarOnComplete('form1:variableControl');}
如上所述,
handleVariableControlOnClick
和handleStopControlOnClick
函数在用户单击上述任一按钮时会发出调用来启动、暂停、重新启动或停止进度栏。在对进度栏执行此类客户端脚本调用的同时,会将 AJAX 请求发送到服务器中。结果是:将调用特定于startOperation
、pauseOperation
、resumeOperation
或stopOperation
的方法。handleProgressBarOnComplete
函数会将第一个按钮的 text 属性更改为 "Start",以便用户可以重新启动该任务。 注意:在某些情况下,IDE 可能会在代码中插入一个额外的startOrResumeTask
方法,该方法会禁止对代码进行编译。要修复此错误,请删除这个额外的方法。 -
打开 Page1 的 "JSP" 视图,然后添加 progressBar1 的
interval
、percentage
、failed
和percentageText
属性,如以下粗体内容所示:代码样例 3:ProgressBar1 的属性 <bp:progressBar binding="#{Page1.progressBar1}" id="progressBar1" interval="#{SessionBean1.taskMap.progressBar1.interval}" percentage="#{SessionBean1.taskMap.progressBar1.percentage}" failed="#{SessionBean1.taskMap.progressBar1.failed}" percentageText="#{SessionBean1.taskMap.progressBar1.percentageText}" onComplete="function() ... resumeOperation=...
进度栏的这些属性与taskMap
中 SimpleTask 实例(与 progressBar1 关联)的相应属性绑定在一起。由于属性编辑器的局限性,您只能将这些代码直接添加到 JSP 源代码中。 -
生成并运行该应用程序。单击 "Start" 按钮启动任务。进度栏将随着任务的进展情况填充进度,并且文本消息也会随之不断地更新以表示任务完成的进度百分比(例如 25%)。"Start" 按钮会变为 "Pause"。
- 单击 "Pause" 按钮(会变为 "Resume")和 "Cancel" 按钮,继续观察应用程序的运行情况。
执行更多操作 #1:添加一个任务进度不确定的进度栏
在本部分,您将添加一个任务进度并不确定的进度栏,它通过移动的方式来表示任务正在进行中,而不是通过填充进度栏来显示任务完成的百分比情况。如果您无法确定任务完成的具体进度情况,则使用任务进度不确定的进度栏是一种较好的方式。本部分构建的页面应如下图所示:
图 3:添加一个任务进度不确定的进度栏 -
打开 Page1 的“设计”视图。复制进度栏组件和网格面板组件并将它们粘贴到原组件的下方。 注意:此教程部分将使用这些组件的缺省
id
属性:progressBar2
、controlPanel1
、variableControl1
和stopControl1
。 -
选择新的进度栏组件并更改
onComplete
属性以使其指向variableControl1
:function() {handleProgressBarOnComplete('form1:variableControl1');}
-
选择新的 "Start" 按钮并更改
onClick
属性以使其指向progressBar2
:handleVariableControlOnClick(this, 'form1:progressBar2', false)
-
选择新的 "Cancel" 按钮并更改
onClick
属性以使其指向variableControl1
和progressBar2
:handleStopControlOnClick('form1:variableControl1', 'form1:progressBar2')
-
打开 Page1 的 "JSP" 视图。找到 progressBar2 的代码,该代码位于
</h:panelGrid>
行的后面。修改 progressBar2 的四个属性(以粗体显示),使它们与 progressBar2 关联。代码样例 4:progressBar2 的属性 </h:panelGrid> <bp:progressBar binding="#{Page1.progressBar2}" failed="#{SessionBean1.taskMap.progressBar2.failed}" id="progressBar2" interval="#{SessionBean1.taskMap.progressBar2.interval}" onComplete="function() ... percentage="#{SessionBean1.taskMap.progressBar2.percentage}" percentageText="#{SessionBean1.taskMap.progressBar2.percentageText}" resumeOperation=...
由于空间的限制,上述代码中的某些行已分成两行显示。 -
打开
SessionBean1.java
文件,然后将以下行附加到SessionBean1.init
方法的结尾处。taskMap.put("progressBar2", new SimpleTask("progressBar2", 241, 100, true));
此代码在taskMap
中添加一个新的 SimpleTask 实例。第二个进度栏将监视该任务。参数true
将传递至 SimpleTask 构造函数,表明这是一个进度不确定的任务。 -
生成并运行项目。单击本部分添加的 "Start" 按钮来启动进度不确定的任务。 一个小的矩形框将从左至右移动,并出现一条文本消息 "(time remaining unknown)"(时间未知),直至任务完成为止。
-
单击 "Pause"、"Resume" 和 "Cancel" 按钮,继续观察应用程序的运行情况。下图显示了正在运行的两个进度栏。
图 4:运行中的进度栏
执行更多操作 #2:模拟一个失败的任务
下面您将修改进度栏 组件来显示一个失败的任务。- 打开 Page1 的“设计”视图。
-
更改 variableControl 按钮(第一个 "Start" 按钮)的
onClick
属性,以使其使用true
而不是false
:handleVariableControlOnClick(this, 'form1:progressBar1', true)
此代码在 AJAX 请求中发送一个名为doomed
且值为true
的请求参数。页面 Bean 中的startOrResumeTask
方法将检索该参数并将其作为一个参数传递给 SimpleTaskstart
方法。 -
更改 variableControl1 按钮(第二个 "Start" 按钮)的
onClick
属性,以使其使用true
而不是false
:handleVariableControlOnClick(this, 'form1:progressBar2', true)
-
将 progressBar1 的
onFail
属性设置为:function() {handleProgressBarOnFail('form1:variableControl');}
当任务失败时,handleProgressBarOnFail
函数会将第一个按钮的 text 属性更改为 "Start",以便用户可以重新启动该任务。 -
将 progressBar2 的
onFail
属性设置为:function() {handleProgressBarOnFail('form1:variableControl1');}
-
生成并运行项目。 此时第一个进度栏在进度达到 25% 时运行失败。第二个进度栏表示的是一个进度不确定的任务,虽然其文本消息未说明任务进度的百分比,但它也同样运行失败了。
执行更多操作 #3:更改进度栏的样式
最后,您将在项目的stylesheet.css
文件中更改进度栏的样式。- 通过在“项目”窗口中双击 "ProgressBarExample" >“Web 页”> "resources" > "stylesheet.css" 节点,打开样式表。
-
添加下面以粗体显示的代码(用于更改进度栏的颜色和字体),然后保存文件。
代码样例 5:用于设置进度栏颜色的样式表代码 .bpui_progressbar_portionComplete { background: blue !important; } .bpui_progressbar_portionRemaining { background: lightgrey !important; } .bpui_progressbar_percentageText { color: blue; font-size: 14px; font-weight: bold; } .bpui_progressbar_barArea { height: 9px !important; }
-
打开 Page1 的“设计”视图以查看进度栏的变化,如下图所示。
图 5:设置了样式的进度栏
小结
现将进度栏组件的重要功能归纳如下:
- 进度栏组件既支持任务进度确定的用例,也支持任务进度不确定的用例。进度栏组件会将 -1% 解释为不确定的任务进度。
- 通过
startOperation
、pauseOperation
、resumeOperation
和stopOperation
事件(将其与页面 Bean 中的方法绑定),进度栏组件支持启动、暂停、重新启动和停止功能。 - 通过一个可绑定的布尔型
failed
属性,进度栏组件还提供任务失败支持。 - 通过
onComplete
和onFail
等一些高级的属性,进度栏组件支持定制的脚本功能。您可以将定制的 JavaScript 合并到.js
文件中,然后使用一个引用该文件的脚本组件。 - 进度栏组件还提供样式定制支持。
以下是本教程提供的有关使用进度栏组件的一些提示:
- 在会话范围内维持一个任务对象的映射,即一个进度栏监视一项任务。
- 支持长时间运行的任务使用单独的线程。您可以将
SimpleTask.java
作为模型编写用于表示特定任务的类。SimpleTask.java
维持了对线程的引用,并通过方法调用来启动(或重新启动)、暂停和取消任务,此外,它还具有表示轮询时间间隔、进度百分比、文本内容以及任务是否失败的属性。
另请参见:
-