文档章节

为Struts2 应用程序创建进度条(等待页面)

J
 Java编程思想
发布于 2014/01/04 15:43
字数 2503
阅读 301
收藏 22

     

     对于一些需要较长时间才能完成的任务,在Web开发中,会由HTTP协议会因为超时而断开而面临许多风险,这是在桌面开发不曾遇到的。Struts 2提供的execAndWait拦截器就是为了处理和应付这种情况而设计的。注意,该拦截器不在"defaultStack"中,所以必须在使用它的动作里声明它,并且必须放在拦截器栈的最后一个。
      使用了该拦截器后,动作依然正常执行,只是该拦截器会分配一个后台线程处理动作的运行,并在动作完成之前把用户带到一个"等待"页面。,该页面每隔一段时间刷新一次,直到那个后台线程执行完毕为止。如果用户随后又触发了同一个动作,但顶一个动作尚未执行完毕,这个拦截器将继续向用户发送"等待"结果;如果他已经执行完毕,用户会看到该动作的最终结果。
      "等待"结果的行为与"dispatcher"结果的行为很相似,但是要注意的是,"等待"结果对应的视图带有如下的meta标签:
<meta http-equiv="refresh" content="5;url=/Struts2/default_progressbar.action"/>
该标签的作用就每隔多少秒就重新加载一次同样的URL。这里"5"表示5秒,"url=/Struts2/default_progressbar.action"表示要加载的URL。
   Struts 2是一个灵活强大的框架,如果你不喜欢Struts 2提供的默认"等待页面",你也可以自己设计自己的等待页面,若在动作声明中,没有找到"等待"结果,将使用默认值。

execAndWait拦截器
execAndWait拦截器 可以接收以下参数:
  • threadPriority:分配给相关线程的优先级,默认值为Thread.NORM_PRIORITY。
  • delay:向用户发送"等待"结果前的毫秒数,默认值为0。如果你不想立刻发送"等待"结果,可以将该参数设置为一个值。例如,你想让动作超过2秒还未完成时才发送"等待"结果,需要将其值设置为2000.
  • delaySleepInterval:每隔多少毫秒唤醒主线程(处理动作的后台线程)去检查后台线程是否已经处理完成,默认值是100。这个值设为0时无效。

模拟长时间运行的Action

      为了示例,首先来模拟一个运行时间长的Action:在这个Action中首先定义了一个int类型的progress属性及其getter/setter,用来向外界返回当前任务的完成进度。在execute方法中,让Action所在的线程在每次循环的时候sleep一秒钟,每次循环把进度加十。

这样,随着外界不断访问progress属性,就可以知道当前任务运行的进度了。示例代码如下:

 

java代码:
  1. public class WaitAction extends ActionSupport{  
  2.     /** 
  3.      * 准备向等待页面返回工作的进度 
  4.      */  
  5.     private int progress;  
  6.     public int getProgress() {  
  7.         return progress;  
  8.     }  
  9.     public void setProgress(int progress) {  
  10.         this.progress = progress;  
  11.     }  
  12.       
  13.     public String execute() throws Exception {  
  14.         //循环十次,每次线程睡1秒,且进度加10  
  15.         for (int i=0;i<10;i++){  
  16.             Thread.sleep(1000L);  
  17.             progress += 10;  
  18.         }  
  19.         return SUCCESS;  
  20.     }  
  21. }  

19.2.2配置Action

       首先,在配置Action的时候,要让这个Action引用execAndWait拦截器,而且,这个拦截器会中止声明在它以后的拦截器的执行,因此这个拦截器的引用要出现在defaultStack拦截器栈之后。

       其次,还要为这个Action声明一个名称为wait的Result,由它来指定具体的等待页面。示例代码如下:

 

java代码:
  1. <package name="helloworld" extends="struts-default">  
  2.     <action name="waitAction" class="cn.javass.wait.WaitAction">  
  3.         <interceptor-ref name="defaultStack"/>  
  4.         <interceptor-ref name="execAndWait"/>  
  5.         <result>/wait/success.jsp</result>  
  6.         <result name="wait">/wait/wait.jsp</result>  
  7.     </action>  
  8. </package>  

19.2.3实现“进度条”页面

       由于HTTP页面在显示之后,不会再与服务器交互,所以,要不断的刷新这个“进度条”页面才行。

可以简单的使用<html>标签中的<meta>标签来设置这个页面不断进行自我刷新。示例代码如下:

 

java代码:
  1. <%@ page language="java" contentType="text/html; charset=gb2312"  
  2.     pageEncoding="gb2312"%>  
  3. <%@taglib prefix="s" uri="/struts-tags" %>  
  4. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"  
  5.  "http://www.w3.org/TR/html4/loose.dtd">  
  6. <html>  
  7. <head>  
  8. <meta http-equiv="Content-Type" content="text/html; charset=gb2312">  
  9. <meta http-equiv="refresh" content="2;url=/helloworld/waitAction.action">  
  10. <title>Insert title here</title>  
  11. </head>  
  12. <body>  
  13.     您好,任务还未完成,已经运行到了任务的<s:property value="progress"/>%  
  14. </body>  
  15. </html>  

       <meta http-equiv="refresh" content="2;url=/helloworld/waitAction.action">这句话代表了当前页面会在显示2秒之后访问” /helloworld/waitAction.action”这个URL。由于wait.jsp就是从这个Action中跳转出来的,所以就相当于每隔2秒就刷新一次wait.jsp页面。同样可以通过<s:property/>标签访问值栈。

19.2.4实现完成页面

       实现一个完成页面,在完成页面中,简单的告知用户已经成功执行。示例代码如下:

 

java代码:
  1. <%@ page language="java" contentType="text/html; charset=gb2312"  
  2.     pageEncoding="gb2312"%>  
  3. <head>  
  4. <meta http-equiv="Content-Type" content="text/html; charset=gb2312">  
  5. </head>  
  6.     恭喜您,任务结束!  

19.2.5运行测试

       在浏览器的地址栏输入“http://localhost:9080/helloworld/waitAction.action”,来直接访问waitAction。

在访问这个WaitAction的时候,第一次访问会使execute方法开始运行。但是,由于引用了execAndWait拦截器,并不是一直等到execute方法运行完之后再跳转到下一个页面,而是马上跳转到struts.xml中注册的名为wait的Result,也就是wait.jsp。

在wait.jsp中仍然可以访问值栈里面的值,因此,通过访问了progress属性来显示当前任务运行的进度。如下图所示:

图19.1  显示任务进度一

在wait.jsp,又指定了每隔2秒访问一次WaitAction,这时候,只要execute方法还没运行完,就马上再次转发到名为wait的Result,依次类推,直到execute方法运行完之后。因此页面显示的进度数据会一直增加,如图所示:

图19.2  显示任务进度二

       因此,如果不引用execAndWait拦截器,在访问WaitAction的时候,本应该等到10秒后浏览器才有反应。但是,现在引用了execAndWait拦截器,在访问WaitAction的时候,马上跳转到了wait.jsp,而且每隔2秒刷新一次,直到10秒之后,直到execute方法运行完成,浏览器正确的跳转到success.jsp。如下图所示:

图19.3 任务结束

19.2.6图形化的进度条

       看到这里,肯定有朋友会说,这哪里像是进度条啊,明明只是显示了一个运行进度而已。确实,从表现上看,不像我们熟悉的进度条,尤其是不像图形化的进度条。

1:JavaScript的图形化进度条

       其实,要实现图形化的进度条也很简单,使用Javascript就可以很方便的实现。先看个最简单的Javascript的进度条的实现,示例代码如下:

 

java代码:
  1. <%@ page language="java" contentType="text/html; charset=gb2312"  
  2.     pageEncoding="gb2312"%>  
  3. <style type="text/css">  
  4. #out{width:300px;height:20px;background:#EEE000;}  
  5. #in{width:10px; height:20px;background:#0000ff;color:white;text-align:center;}  
  6. </style>  
  7. </HEAD>  
  8. <BODY onload="start();" >  
  9. <div id='out'>  
  10.     <div id="in" style="width:10%">10%</div>  
  11. <div>  
  12. <script type="text/javascript">  
  13.     var i=0;  
  14.     function start(){  
  15.         ba=setInterval("begin()",100);  
  16.     }  
  17.     function begin(){  
  18.         i+=1;  
  19.         if(i<=100){  
  20.             document.getElementById("in").style.width=i+"%";  
  21.             document.getElementById("in").innerHTML=i+"%";  
  22.         }else{  
  23.             clearInterval(ba);  
  24.             document.getElementById("out").style.display="none";  
  25.             document.write("进度条运行成功");  
  26.         }  
  27.     }  
  28. </script>  
  29. </BODY>  

具体的Javascript的知识,这里就不去深入了,要注意下面几点:

  • 进度条的效果是通过两个Div来实现的,id为out的div作为底框,id为in的div作为动态显示进度的进度框
  • 启动方法是<body>元素的onload属性所指定的方法
  • Start方法里面的setInterval(表达式,间隔时间),意思是:启动后,每隔指定的间隔时间,就执行前面的表达式一次,这个方法相当于一个定时器
  • 在begin方法里面,通过动态的改变id为in的div框所包含的文字,从而实现动态显示进度的效果
  • 运行到最后,一定要记得清除掉setInterval所设置的定时器,用的是clearInterval方法

当然,使用Javascript来实现进度条有很多种方式,这里只是其中的一种而已。

2:把Struts2的进度条图形化

       接下来把前面的wait.jsp页面显示的进度,改成图形化的进度条的形式。

       同样需要使用Javascript来图形化的显示进度条,只不过具体的进度数据应该从Struts2的waitAction中去获取,也就是直接把从Action中获取的进度数据,直接赋值给Javascript,然后通过Javascript来显示进度条。示例代码如下:

 

java代码:
  1. <%@ page language="java" contentType="text/html; charset=gb2312"  
  2.     pageEncoding="gb2312"%>  
  3. <%@taglib prefix="s" uri="/struts-tags" %>  
  4. <html>  
  5. <head>  
  6. <style type="text/css">  
  7. #out{width:300px;height:20px;background:#EEE000;}  
  8. #in{width:10px; height:20px;background:#0000ff;color:white;text-align:center;}  
  9. </style>  
  10. <meta http-equiv="Content-Type" content="text/html; charset=gb2312">  
  11. <meta http-equiv="refresh" content="2;url=/helloworld/waitAction.action">  
  12. <title>Insert title here</title>  
  13. </head>  
  14. <body>  
  15. <BODY onload="start();" >  
  16. <div id='out'>  
  17.     您好,任务还未完成,已经运行到了任务的<div id="in" style="width:10%">10%</div>  
  18. <div>  
  19. <script type="text/javascript">     
  20.     function start(){  
  21.         ba=setInterval("begin()",100);  
  22.     }  
  23.     function begin(){  
  24.         var i = <s:property value="progress"/>;  
  25.         if(i<=100){  
  26.             document.getElementById("in").style.width=i+"%";  
  27.             document.getElementById("in").innerHTML=i+"%";  
  28.         }else{  
  29.             clearInterval(ba);  
  30.             document.getElementById("out").style.display="none";  
  31.             document.write("进度条运行成功");  
  32.         }  
  33.     }  
  34. </script>  
  35. </BODY>  
  36. </html>  

       最重要的变化就在加粗的那句话,把从Action获取的数据直接设置给了Javascript,要注意这个过程是在服务端完成的,到了客户端,值已经设置好了,因此Javascript同样能正常地运行。

       运行URL:http://localhost:9080/helloworld/waitAction.action,测试一下看看效果,如下图所示:

图19.4  Struts2的进度条图形化

       进度条会不断滚动,直到运行结束,转向success.jsp为止。


     本文参考自:http://www.cnblogs.com/suxiaolei/archive/2011/11/06/2232009.html

                    http://sishuok.com/forum/blogPost/list/4174.html


本文转载自:http://sishuok.com/forum/blogPost/list/4174.html

J
粉丝 28
博文 167
码字总数 10302
作品 0
广州
程序员
私信 提问
用户体验设计----(进度指示器)

目前只是分享一下,用户等待的形式和目前一些常见类型,代码正在整理中,会在之后的博客中展示,欢迎大家指正和讨论用户体验的方式和实现,以及何为最优的用户体验。 现在,你必须要理解进度...

天机
2016/08/05
31
0
网页加载进度条的JS程序开发思路与实际应用

一款好的产品,都需要有一个漂亮的loading界面。lodaing界面不仅能给用户带来良好的体验,而且有效的消除了程序加载等待过程中的枯躁感。 loading进度条更是对当前加载进度的一个良好反馈。从...

武文海
2015/07/01
164
0
Android开发指南-用户界面-用户通知

通知用户Notifying the User 某些情况下需要通知用户你的应用程序中发生了一个事件。一些事件请求用户应答而另外一些则不需要。比如: · 当一个事件比如保存文件结束时,应该出现一条消息确...

JavaGG
2010/03/24
248
0
struts2 上传文件添加进度条

为了给用户更好体验,最进在struts2添加了上传进度条让用户知道上传过程时间,增加有好度。 由于以前做个 文件上传 没有用过 组件进行解析,直接用servlet 解析的,而现在 struts2 框架使用 ...

hlevel
2013/08/14
7.6K
6
等待界面或者进度条的问题

Java Swing : 做了一个加载数据的Swing程序,当数据很多时,打开Swing的界面速度很慢,这中间想做一个等待界面或者进度条。当运行Swing程序时,跳出等待界面或者进度条,当Swing的界面显示在...

wangaowell
2013/09/22
975
3

没有更多内容

加载失败,请刷新页面

加载更多

rime设置为默认简体

转载 https://github.com/ModerRAS/ModerRAS.github.io/blob/master/_posts/2018-11-07-rime%E8%AE%BE%E7%BD%AE%E4%B8%BA%E9%BB%98%E8%AE%A4%E7%AE%80%E4%BD%93.md 写在开始 我的Arch Linux上......

zhenruyan
今天
5
0
简述TCP的流量控制与拥塞控制

1. TCP流量控制 流量控制就是让发送方的发送速率不要太快,要让接收方来的及接收。 原理是通过确认报文中窗口字段来控制发送方的发送速率,发送方的发送窗口大小不能超过接收方给出窗口大小。...

鏡花水月
今天
10
0
OSChina 周日乱弹 —— 别问,问就是没空

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @tom_tdhzz :#今日歌曲推荐# 分享容祖儿/彭羚的单曲《心淡》: 《心淡》- 容祖儿/彭羚 手机党少年们想听歌,请使劲儿戳(这里) @wqp0010 :周...

小小编辑
今天
1K
11
golang微服务框架go-micro 入门笔记2.1 micro工具之micro api

micro api micro 功能非常强大,本文将详细阐述micro api 命令行的功能 重要的事情说3次 本文全部代码https://idea.techidea8.com/open/idea.shtml?id=6 本文全部代码https://idea.techidea8....

非正式解决方案
今天
5
0
Spring Context 你真的懂了吗

今天介绍一下大家常见的一个单词 context 应该怎么去理解,正确的理解它有助于我们学习 spring 以及计算机系统中的其他知识。 1. context 是什么 我们经常在编程中见到 context 这个单词,当...

Java知其所以然
昨天
9
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部