跳至内容 Java Solaris 社区 Sun 商店 加入 SDN 我的个人档案 加入的益处
 
使用 AJAX 进度栏组件
2006 年 7 月 [修订号:V2.1-2]  
本教程介绍了如何通过 Sun Java Studio Creator 的集成开发环境 (Integrated Development Environment, IDE) 构建一个使用 Java BluePrints AJAX 进度栏组件样例的 Web 应用程序。此外,本教程还介绍了一些进度栏的应用实例。首先,您需要为可以确定任务进度的用例配置进度栏。在本例中,进度栏将通过百分比来表示任务的完成进度。接下来,您需要为任务进度不确定的用例配置进度栏。对于这种情况,进度栏并不使用百分比来表示任务的完成进度,而只表示某项任务正在进行当中,这是因为此任务的进度情况是未知的。最后,您需要配置一个用于处理失败任务的进度栏。

通过 IDE 中提供的样例 Java BluePrints AJAX 组件,可以帮助您了解 AJAX 技术并能很好地说明 AJAX 是如何与 Java Studio Creator IDE 结合使用的。有关 AJAX 技术的相关说明,请参见 AJAX 和 Sun Java Studio Creator 2
 
目录
 
设置应用程序
修改会话 Bean
创建一个任务进度确定的进度栏
为进度栏添加代码
执行更多的操作 #1:添加一个任务进度不确定的进度栏
执行更多的操作 #2:模拟一个失败的任务
执行更多的操作 #3:更改进度栏的样式
[spacer] 此页上的内容适用于 Sun Java Studio Creator 2
 
本教程中使用的外部代码
» pb.js
 

设置应用程序

 
在本教程中,首先将 Java BluePrints AJAX 组件导入到 IDE 中。然后创建一个项目,并添加两个文件:SimpleTask.javapb.jsSimpleTask.java 将模拟一个在单独线程中执行的服务器端任务。无论用户何时启动(或重新启动)此任务,SimpleTask.java 中的 start 方法都会产生一个新的线程,该线程或者休眠,或者递增计数器的值。pb.js 文件包含了一些函数,供应用程序中与 JavaScript 相关的组件属性调用。这些属性包括进度栏的 onCompleteonFail 属性、按钮的 onClick 属性和表单的 onSubmit 属性。
  1. 下载并导入最新版本的 AJAX 组件(如果您尚未执行此操作)。

    注意:本教程使用了最新版本的进度栏组件。要了解您是否使用了最新的版本,请将组件拖至页面上并在其“属性”窗口的“事件”类别下验证是否存在 pauseOperationresumeOperation 属性。

  2. 下载 SimpleTask.javapb.js 并将它们保存到您的文件系统中。

  3. 创建一个新的 Web 应用程序项目,并将其命名为 ProgressBarExample

    将在可视设计器中打开 ProgressBarExample 的初始页。

  4. 按照以下操作,将 SimpleTask.java 添加到项目中:

    1. 在主菜单中,选择“文件”>“添加现有项”>“Java 源代码”。导航至您保存 SimpleTask.java 所在的目录。选中该文件并单击“添加”。IDE 会将 SimpleTask 类添加到 ProgressBarExample 包中。

    2. 在“项目”窗口中双击 SimpleTask.java 节点,将以下包语句添加到源代码中:
      package progressbarexample;
    3. 在主菜单中,选择“生成”>“编译 "SimpleTask.java"”。

    4. 关闭项目,然后再重新打开项目。执行此步骤后才可以在设计时使用 SimpleTask 类。

  5. 按照以下操作,将 pb.js JavaScript 文件添加到项目中:

    1. 选择“文件”>“添加现有项”>“其他(所有文件)”。导航并选择 pb.js,然后单击“添加”。在“项目”窗口中,您会注意到 pb.js 位于“源包”> "progressbarexample" 节点下。

    2. 右键单击 pb.js,然后从弹出式菜单中选择“剪切”。

    3. 展开“Web 页”节点,右键单击 "resources" 节点并选择“粘贴”。pb.js 文件会被移动至“Web 页”> "resources" 节点下。
 

修改会话 Bean

 
接下来,您将添加并配置该项目的会话 Bean 属性。
  1. 如有必要,请在可视设计器中打开 Page1,这样“概要”窗口就会处于可见状态。

  2. 在“概要”窗口中,右键单击 "SessionBean1" 节点,然后选择“添加”>“属性”。

  3. 对于出现的“新建属性模式”对话框,在“名称”文本框中键入 taskMap,在“类型”文本框中键入 HashMap(请注意“名称”和“类型”字段是区分大小写的),并将“模式”设置为只读,如下图所示。单击“确定”。
     
    图 1:“新建属性模式”对话框
    图 1:“新建属性模式”对话框
     
  4. 双击 "SessionBean1" 节点可打开源文件。

    代码中出现的错误标注表明未找到 HashMap 类。

  5. SessionBean1.java 中的任意位置单击鼠标右键,并从弹出式菜单中选择“修复导入”以自动添加下列 import 语句:
    import java.util.HashMap;
  6. 将下面以粗体显示的代码行附加到 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:进度页的设计
图 2:进度页的设计
 
  1. 在可视设计器中打开 Page1。

  2. 从组件面板的 "BluePrints AJAX Components" 类别中,将一个 "Progress Bar" 组件拖至页面上。在本教程中,将使用 progressBar1 这一缺省的 id 属性。

    注意:"Progress Bar" 组件应如上图 2 中所示。如果 "Progress Bar" 组件显示不正确,请在可视设计器中单击鼠标右键并从弹出式菜单中选择“刷新”。

  3. 从组件面板的“布局”类别中拖动一个“网格面板”组件,将其放置在 "Progress Bar" 组件的右侧。将“网格面板”的 id 属性设置为 controlPanel,并将 columns 属性设置为 2

  4. 从组件面板的“基本”类别中拖动两个“按钮”组件放置到“网格面板”上。请确保在放置“按钮”组件时,“网格面板”组件的外框呈蓝色实线。

  5. 为第一个按钮设置以下属性:
     
    属性     
    id
    variableControl
    text
    Start
    onClick
    handleVariableControlOnClick(this, 'form1:progressBar1', false)
     
    handleVariableControlOnClick 函数将调用 JavaScript 以便在用户单击按钮时启动、暂停和重新启动进度栏。

  6. 为第二个按钮设置以下属性:
     
    属性     
    id
    stopControl
    text
    Cancel
    onClick
    handleStopControlOnClick('form1:variableControl', 'form1:progressBar1')
     
    handleStopControlOnClick 函数将调用 JavaScript 来停止进度栏的运行。

  7. 在“概要”窗口中,选中 form1。在“属性”窗口中,将表单的 onSubmit 属性设置为 return handleFormOnSubmit()

    此 JavaScript 函数会在用户单击其中任一按钮时阻止提交页面。

  8. 从组件面板的“高级”类别中,将一个 "Script" 组件拖至页面上。

    “概要”窗口将在 "Page1" 部分的下面显示 "script1"。这一不可见的组件用于在呈现的 HTML 标记中声明 script 元素。

  9. 在“属性”窗口中,将 "Script" 组件的 url 属性设置为 /resources/pb.js。请注意此属性需要一个前导的正斜杠 (/)。
 

为进度栏添加代码

 
在本部分,您将为项目的 Java 源代码添加四个方法。这些方法用于执行以下操作并成为 "Progress Bar" 组件的“事件”属性。
  • 启动或重新启动 AJAX 请求中指示的任务。
  • 暂停 AJAX 请求中指示的任务。
  • 停止 AJAX 请求中指示的任务。
  • 提取发送 AJAX 请求的 "Progress Bar" 组件的 id(例如,progressBar1)。
  1. 在 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 的 startOrResumeTaskpauseTaskstopTask 方法。这些方法会调用 getTaskIdFromAjaxRequest 方法,该方法将提取 bpui_progressbar_clientId 请求参数中的组件 id(如 progressBar1)。这些方法使用组件 id 来检索 taskMap 中的 SimpleTask 实例,然后调用此任务的 startpausecancel 方法。

  2. 在 Page1 的源代码中单击鼠标右键,然后从弹出式菜单中选择“修复导入”。

    IDE 将添加以下 import 语句来修复“找不到类”的错误:
    import java.util.Map;
    import javax.faces.component.NamingContainer;
    import javax.faces.context.FacesContext;
    		
  3. 返回到 Page1 的设计视图,为 "Progress Bar" 组件设置以下属性:
     
    属性     
    pauseOperation   
    pauseTask()
    resumeOperation
    startOrResumeTask()
    startOperation
    startOrResumeTask()
    stopOperation
    stopTask()
    onComplete
    function() {handleProgressBarOnComplete('form1:variableControl');}
     
    如上文所述,handleVariableControlOnClickhandleStopControlOnClick 函数在用户单击上述任一按钮时会发出调用来启动、暂停、重新启动或停止进度栏。在对进度栏执行此类客户端脚本调用的同时,会将 AJAX 请求发送到服务器中。结果是:将调用特定于 startOperationpauseOperationresumeOperationstopOperation 的方法。

    handleProgressBarOnComplete 函数会将第一个按钮的文本内容改为 "Start",以便用户可以重新启动该任务。

  4. 打开 Page1 的 JSP 视图,然后添加 progressBar1 的 intervalpercentagefailedpercentageText 属性,如以下粗体内容所示:
     
    代码样例 3:ProgressBar1 的属性
    <ui:form binding="#{Page1.form1}" id="form1" onSubmit="return handleFormOnSubmit()"> 
     <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=...
     
    进度栏的这些属性与 SimpleTask 实例的相应属性进行了绑定,其中 SimpleTask 实例由 taskMap 中的 progressBar1 来控制。由于属性编辑器的局限性,您只能将这些代码直接添加到 JSP 源代码中。

  5. 生成并运行该应用程序。单击 "Start" 按钮启动任务。

    进度栏将随着任务的进展情况填充进度,并且文本消息也会随之不断地更新以表示任务完成的进度百分比(例如 25%)。"Start" 按钮会变为 "Pause"。

  6. 单击 "Pause" 按钮(会变为 "Resume")和 "Cancel" 按钮,继续观察应用程序的运行情况。
 

执行更多的操作 #1:添加一个任务进度不确定的进度栏

 
在本部分,您将添加一个任务进度并不确定的进度栏,它通过移动的方式来表示任务正在进行中,而不是通过填充进度栏来显示任务完成的百分比情况。如果您无法确定任务完成的具体进度情况,则使用任务进度不确定的进度栏是一种较好的方式。本部分构建的页面应如下图所示:
 
图 3:添加一个任务进度不确定的进度栏
图 3:添加一个任务进度不确定的进度栏
 
  1. 打开 Page1 的设计视图。复制 "Progress Bar" 和“网格面板”组件并将它们粘贴到原组件的下方。

    注意:此部分的教程将使用这些组件的缺省 id 属性:progressBar2controlPanel1variableControl1stopControl1

  2. 选中新的 "Progress Bar" 组件并更改 onComplete 属性,使其指向 variableControl1

    function() {handleProgressBarOnComplete('form1:variableControl1');}

  3. 选中新的 "Start" 按钮并更改 onClick 属性,使其指向 progressBar2

    handleVariableControlOnClick(this, 'form1:progressBar2', false)

  4. 选中新的 "Cancel" 按钮并更改 onClick 属性,使其指向 variableControl1progressBar2

    handleStopControlOnClick('form1:variableControl1', 'form1:progressBar2')


  5. 打开 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=...
     
    由于空间的限制,上述代码中的某些行已被分成两行来表示。

  6. 打开 SessionBean1.java 文件,在 SessionBean1.init 方法的结尾处附加以下行:

    taskMap.put("progressBar2", new SimpleTask("progressBar2", 241, 100, true));

    此代码会将新的 SimpleTask 实例添加到 taskMap 中。第二个进度栏将监视该任务。参数 true 将传递至 SimpleTask 构造函数,表明这是一个进度不确定的任务。

  7. 生成并运行该项目。单击本部分添加的 "Start" 按钮来启动进度不确定的任务。

    一个小的矩形框将从左向右移动,并出现一条文本消息 "(time remaining unknown)"(时间未知),直至任务完成为止。

  8. 单击 "Pause"、"Resume" 和 "Cancel" 按钮,继续观察应用程序的运行情况。下图显示了正在运行的两个进度栏。
     
    图 4:运行中的进度栏
    图 4:运行中的进度栏
     

执行更多的操作 #2:模拟一个失败的任务

 
下面您可以修改进度栏组件来显示一个失败的任务。
  1. 打开 Page1 的设计视图。

  2. 更改 variableControl 按钮(第一个 "Start" 按钮)的 onClick 属性,以便它使用 true 而不是 false

    handleVariableControlOnClick(this, 'form1:progressBar1', true)

    通过此代码,一个名为 doomed 的请求参数将以 true 值的方式随 AJAX 请求一起发送。页面 Bean 中的 startOrResumeTask 方法将检索该参数并将其作为一个参数传递给 SimpleTask start 方法。

  3. 更改 variableControl1 按钮(第二个 "Start" 按钮)的 onClick 属性,以便它使用 true 而不是 false

    handleVariableControlOnClick(this, 'form1:progressBar2', true)

  4. 为 progressBar1 设置 onFail 属性:

    function() {handleProgressBarOnFail('form1:variableControl');}


    handleProgressBarOnFail 函数会在任务失败时将第一个按钮的文本内容更改为 "Start",以便用户可以重新启动该任务。

  5. 为 progressBar2 设置 onFail 属性:

    function() {handleProgressBarOnFail('form1:variableControl1');}


  6. 生成并运行项目。

    此时第一个进度栏在进度达到 25% 时运行失败。第二个进度栏表示的是一个进度不确定的任务,虽然其文本消息未说明任务进度的百分比,但它也同样运行失败了。
 

执行更多的操作 #3:更改进度栏的样式

 
最后,您将在项目的 stylesheet.css 文件中更改进度栏的样式。
  1. 通过在“项目”窗口中双击 "ProgressBarExample" >“Web 页”> "resources" 下的 "stylesheet.css" 节点,可以打开样式表。

  2. 添加下面以粗体显示的代码(将会更改进度栏的颜色和字体),然后保存文件。
     
    代码样例 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;
    }
     
  3. 打开 Page1 的设计视图以查看进度栏的变化,如下图所示。
     
    图 5:运行中样式更改后的进度栏
    图 5:运行中样式更改后的进度栏
     

小结

 
现将进度栏组件的重要功能归纳如下:
  • 进度栏组件既支持任务进度确定的用例,也支持任务进度不确定的用例。进度栏组件会将 -1% 解释为不确定的任务进度。
  • 通过 startOperationpauseOperationresumeOperationstopOperation 事件(将其与页面 Bean 中的方法绑定),进度栏组件支持启动、暂停、重新启动和停止功能。
  • 通过一个可绑定的布尔型 failed 属性,进度栏组件还提供任务失败支持。
  • 通过 onCompleteonFail 等一些高级的属性,进度栏组件支持定制的脚本功能。您可以将定制的 JavaScript 合并到 .js 文件中,然后使用一个引用该文件的 Script 组件。
  • 同时,进度栏组件还提供样式定制支持。
以下是本教程提供的有关使用进度栏组件的一些提示:
  • 在会话范围内维持一个任务对象的映射,即一个进度栏监视一项任务。
  • 支持长时间运行的任务使用单独的线程。您可以将 SimpleTask.java 作为模型编写用于表示特定任务的类。SimpleTask.java 维持了对线程的引用,并通过方法调用来启动(或重新启动)、暂停和取消任务,此外,它还具有表示轮询时间间隔、进度百分比、文本内容以及任务是否失败的属性。
 
另请参见
 
更多的开发者资源
 
有关为开发者提供的更多教程、文章、提示、论坛、更新和专家建议,请访问 Sun Developer Network (SDN) 上的 Java Studio Creator 开发者资源,网址为 http://gceclub.sun.com.cn/prodtech/javatools/jscreator/。
 

此页的最新修改时间:2006 年 7 月 17 日