转自:http://blog.163.com/yinlilin_163/blog/static/1226183020091122103532862/
实时百分比进度条
设计思想:利用ajax(异步JavaScript和XML)技术在执行主action的同时异步调用副action实时读取主action的完成进度并显示在页面。完成进度的计算方法:以下发业务为例--得到需要下发的总数,把总数分成10份,计算得到1/10,2/10,…9/10所对应的次数为多少并记录下来,申请一个计数器,每次的下发计数器加1,自动累加,当达到记录1/10,2/10,…9/10所对应的数时百分比进度自动累加成10%,20%---90%.副action的流传jsp直接获取百分比的值。这范例关键是算法的问题。其他东西都是可以套用的,能够理解算法其他的也就简单了。Ajax的页面流传是不会流转到对应页面的,但是所传的值你是可以得到的。这和我们平时不同。正是因为这个机制使我们能够在不改变原业务action以及流传页面的同时实现实时百分比进度条.
SANBAO项目使用的是sweat框架,结合spring.
实现JSP与java数据的交互,以及java与数据的交互主要的开发流程为:
1, 在数据库中插入你所要加的action名称(提交你所设计好的action名称,以模板的形式提交给项目数据库管理员).
2, 在actionConfig目录下创建action配置文件,主要负责定义action与jsp传输的元素名,类型,传入还是传出,action的处理类以及当action处理完业务逻辑时需要的流转目标页面。如下图所示当创建并配置完action配置文件,需在actionConfig.xml中申明您所加的action配置文件。
3, 创建action处理类。
4,创建显示业务数据的jsp.
根据以上的4步开发过程我们具体要做的分为以下几步:
第一, 在数据库中创建一个副action,在actionConfig中打开主action的配置文件,添加副action的处理类,以及传输的数据和流转到的jsp. 在xml配置文件中的代码如下:
<Actions>
<ActionStep id="RealtimePercentPlan_Step" classname="com.XXX.action.ShowRealtimePercent">
<Data dataName="Result_fix" refElement="system.string" direction="out"/>
<Data dataName="statues" refElement="system.string" direction="inout"/>
</ActionStep>
<Action id="RealtimePercentPlan">
<Description> Search </Description>
<ActionContext/>
<ActionClass id="EnhanceFlow" classname="">
<paramActionStep action="RealtimePercentPlan_Step" id="1" on0Do="next" onOtherDo="return"/>
</ActionClass>
<PresentationConfig>
<ActionDestination method="forward" return_code="0">/jsp/RecallActivityStatusChange/showprectcent.jsp</ActionDestination>
</PresentationConfig>
</Action>
</Actions>
在ActionStep中的Classname属性中申明处理类.
data元素中申明传值的名字和类型传入或者传出.
actionDestination中当return_code为0时 流转到showprectcent.jsp
第二, 写action代码,创建名为ShowRealtimePercent的java文件,具体代码如下:
/*
* 创建日期 2008-11-25
*
* 更改所生成文件模板为
* 窗口 > 首选项 > Java > 代码生成 > 代码和注释
*/
/**
* @author MARS
*
* 更改所生成类型注释的模板为
* 窗口 > 首选项 > Java > 代码生成 > 代码和注释
*/
public class ShowRealtimePercent extends ActionImpl{
private static int percent = 0;//传出的百分比数值
private static int[] arrayPercent=null ;//划分的在总数中的10个值.
private static int plan=0;//百分比计数器.
private static int flag = 1;//分割次数
private static int counter = 0;//次数计数器
private static int spare=0;//剩余值
/* (非 Javadoc)
* @see com.infoservice.frame.web.action.ActionImpl#performExecute(com.infoservice.frame.web.datacontext.ActionContext)
*/
protected int performExecute(ActionContext actionContext) {
System.err.println("=================RecallActivitySSTReport start================");
ActionDataContext context = actionContext.getActionDataContext();
String statues = (String)context.getValue("statues");
System.err.println("statues==========" + statues);
context.setValue("Result_fix",new Integer(percent).toString());
context.setValue("statues",statues);
// percent=0;
System.err.println("=================RecallActivitySSTReport end================");
return 0;
}
//判断传入的值是否为百分比值如果是则是百分比进度加10
public static void setPercent(int number){
//System.err.println("plan============" + plan);
counter++;
if(counter== arrayPercent[plan] && plan < 9){
percent = percent+10;
System.err.println("percent============" + percent);
plan++;
}
}
//根据总数划分百分比进度值。
public static void setNum(int num){
int j = num/10;
spare = num - (j*9);
arrayPercent = new int[10];
for(int i = 0;i< 10;i++){
if(i < 9){
arrayPercent[i]= (i+1)*j;
}else{
arrayPercent[i]= (i)*j+ spare;
}
System.err.println("arrayPercent================" + arrayPercent[i]);
}
}
//检查进度条是否满足条件
public static void contentPercent(){
percent = 0;//传出的百分比数值
arrayPercent = null ;//划分的在总数中的10个值.
plan=0;//百分比计数器.
flag = 1;//分割次数
counter = 0;//次数计数器
spare=0;//剩余值
}
/**
* @return
*/
public static int getFlag() {
return flag;
}
/**
* @param i
*/
public static void setFlag(int i) {
flag = i;
}
}
第三,创建jsp获得action所传出的值.具体代码如下:
<%@ page contentType="text/html; charset=gb2312" language="java" import="java.sql.*" errorPage="" %>
<%
JspHelper helper = new JspHelper(request);
ActionDataContext context =(ActionDataContext) helper.dataContext;
String task = (String)context.getValue("Result_fix");
String statues=(String)context.getValue("statues");
System.err.println("task==============" + task);
System.err.println("statues==============" + statues);
if(statues.equals("create")){
task = "0";
}
System.err.println("task==============" + task);
String res = "";
res = "<percent>" + task + "</percent>";
response.setContentType("text/xml");
response.setHeader("Cache-Control", "no-cache");
out.println("<response>");
out.println(res);
out.println("</response>");
%>
其实这个jsp就是一个xml文件,由于在ajax中异步传值并且显示的机制需要的是xml文件。所以我们把得到的jsp写成xml.
这样一个从action触发到jsp的流程就走完了。我们只需要在原业务的jsp中加入当主action被调用时,异步调用我们新申明的action 就可以实时的把百分比进度显示在jsp页面了。那么百分比进度如何更改呢,我们需要在原业务action中加入副action的一些方法,使计数器发生改变,从而动态得到此时下发到了第几个,以及此时下发的数目在总数中占百分之多少。然后把百分比传出去显示出来。
所以剩下的开发步骤可以分为以下几步:
第一:在原业务逻辑action中加入副action的方法使副action的计数器发生变化从而技术百分比.具体代码如下。
List dealers = AddrConfigManager.getInstance().getAddressList();
String[] msgIDs = new String[dealers.size()];
ShowRealtimePercent.setNum(dealers.size()*(ShowRealtimePercent.getFlag()));
//设置需要下发的总数.
for ( int i = 0; i < dealers.size(); i ++ ){
String s = SeqIDManager.getInstance().getNextVal(SeqIDManager.DEMessageSeqId,conn);
String msgID = TransSeqIDUtil.getInstance().getSeqID(msg.getFromId(),s, MessageUtil.maxDEIdLength);
msg.setDEMessageId(msgID);
msg.setToId((String)dealers.get(i));
asyncSend(msg,conn);
ShowRealtimePercent.setPercent(i);
//更改副action中的计数器使其能够计算得到百分比进度.
}
ShowRealtimePercent.contentPercent();//当业务action做完全部操作时把计数器以及百分比计数器全部清零.
第二, 在原jsp页面调用业务action时候异步调用副action并且从action流转的页面得到百分比进度值显示在页面中.具体代码如下:
<script type="text/javascript">
var xmlHttp;
var bar_color = 'blue';
var span_id = "yellow";
var clear = " "
function createXMLHttpRequest() {
if (window.ActiveXObject) {
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
else if (window.XMLHttpRequest) {
xmlHttp = new XMLHttpRequest();
}
}
function go() {
var url3 ="<%=request.getContextPath()%>/MainServlet?action=RealtimePercentPlan&statues=create";
createXMLHttpRequest();
checkDiv();
xmlHttp.open("GET", url3, true);
xmlHttp.onreadystatechange = goCallback;
xmlHttp.send(null);
}
function goCallback() {
document.form3.style.display = "inline";
if (xmlHttp.readyState == 4) {
if (xmlHttp.status == 200) {
setTimeout("pollServer()", 5000);
}
}
}
function pollServer() {
createXMLHttpRequest();
var url3 ="<%=request.getContextPath()%>/MainServlet?action=RealtimePercentPlan&statues=poll";
xmlHttp.open("GET", url3, true);
xmlHttp.onreadystatechange = pollCallback;
xmlHttp.send(null);
}
function pollCallback() {
if (xmlHttp.readyState == 4) {
if (xmlHttp.status == 200) {
var percent_complete = xmlHttp.responseXML.getElementsByTagName("percent")[0].firstChild.data;
var index = processResult(percent_complete);
for (var i = 1; i <= index; i++) {
var elem = document.getElementById("block" + i);
elem.innerHTML = clear;
elem.style.backgroundColor = bar_color;
var next_cell = i + 1;
if (next_cell > index && next_cell <= 10) {
document.getElementById("block" + next_cell).innerHTML = percent_complete + "%";
}
}
if (index < 10) {
document.getElementById("complete").innerHTML = "下发进行中!";
setTimeout("pollServer()", 5000);
} else {
document.getElementById("complete").innerHTML = "下发已完成,请稍后!";
}
}
}
}
function processResult(percent_complete) {
var ind;
if (percent_complete.length == 1) {
ind = 1;
} else if (percent_complete.length == 2) {
ind = percent_complete.substring(0, 1);
} else {
ind = 10;
}
return ind;
}
function checkDiv() {
var progress_bar = document.getElementById("progressBar");
if (progress_bar.style.visibility == "visible") {
clearBar();
document.getElementById("complete").innerHTML = "";
} else {
progress_bar.style.visibility = "visible"
}
}
function clearBar() {
for (var i = 1; i < 11; i++) {
var elem = document.getElementById("block" + i);
elem.innerHTML = clear;
elem.style.backgroundColor = "white";
}
}
</script>
<form name='form3'>
<table align="center">
<tbody>
<tr><td>
<div id="progressBar" style="padding:2px;border:solid black 1px">
<span id="block1"> </span>
<span id="block2"> </span>
<span id="block3"> </span>
<span id="block4"> </span>
<span id="block5"> </span>
<span id="block6"> </span>
<span id="block7"> </span>
<span id="block8"> </span>
<span id="block9"> </span>
<span id="block10"> </span>
</div>
</td></tr>
<tr><td align="center" id="complete"></td></tr>
</tbody>
</table>
</form>
<script language="javascript">
document.form3.style.display = "none";
</script>
以上为调用副action所需要的代码,如何调用以及调用频率,得到值后如何显示在百分比进度条上。下面为主业务逻辑action的代码只需要在调用主业务逻辑action之前调用刚才实现的go()方法来先调用异步的副action便可.
function goRelease(i){
if(confirm("确定要下发主记录?")==true){
go();
var url3 = "<%=request.getContextPath()%>/MainServlet?action=RecallActivityStatusChange_TM_RECALL_ACTIVITYRelease&activity_id=" + i;
window.location = url3;
//document.frm1.style.display = "inline";
}
}
当做完以上几步,实时百分比进度条就做好了。