导出时间进度条设计流程
对于在企业一般的web项目开发中,往往都会涉及到导入导出,不管是导入还是导出,无非就是在程序开始进入导入或者导出的时候,另起一个定时任务调度窗口,通过异步请求,查看导入或者导出在特定时刻进行到哪一步,然后在导入或者导出的时候的关键点上设定节点的数据存入一个容器中,然后在任务定时调度的时候取出相应的节点数据,然后进行计算分析,前端定时拿到数据,对数据进行判断,然后用一个进度条显示在调度窗体上!
1.在导入或者导出请求到后端的时候,给session设置状态为0;在导入或者导出开始写入数据库或者从数据库开始读取的时候设置session的状态为1,并拿到本次导出或者导出时的总的数据条数m写入session;在数据完全写入数据库或者完全从数据库中读取到内存中的时候设置状态为100,每写入或者写出一条设置数据n进行加一处理,并写入session;如果期间有异常,session设置状态为-1;
2.前端准备好定时调度任务,按30s进行一次调度,每次请求后端时,根据不同时刻,对1session中的数据拿出来进行处理并返回给前端相应的数据信息,前端根据信息如实改变流程状态,如:当session的状态为0的时候,前端拿到数据,显示为正在处理数据。。。。;当session在0-100之间的时候,要拿到m和n的值,然后用n/m取两位小数返回给前端,前端拿到数据,根据小数大小进行显示流程状态;当session的状态为100的时候,前端拿到数据,显示为导出完毕!;当session的状态为-1的时候,说明导出或者导入的过程中已经出错,返回一个返回状态为false,表示导出或者导入出错;如果只是处理数据的接口出错,则直接返回false,前端拿到报获取进度条失败。。。。
前端获取进度条的代码如下(ExtJs4.2):
//获取进度
progressBar: function () {
var task = {
interval: 3000, //每30秒更新
run: function () {
var msgBox = Ext.MessageBox.show({
title: '导出Excel',
//msg: '正在导出......',
progress: true,
width: 313,
buttons: Ext.Msg.OK,
scope: document.body,
fn: function (){
Ext.TaskManager.stop(task);
}
});
Ext.Ajax.request({
url: 'xlsexportcomcodedef/exportXlsProgressBar',
params: {},
disableCaching: true,//禁止缓存
timeout: 30000,//最大等待时间,超出则会触发超时
method: "GET",
success: function (response, opts) {
var ret = Ext.JSON.decode(response.responseText); //JSON对象化
var jsonObj = eval('(' + ret + ')');
var progressBar = jsonObj.progressBar, failure = jsonObj.failure;//,total = jsonObj.totle,count = jsonObj.totleCount
if (failure) {
msgBox.hide();
Ext.TaskManager.stop(task);
RMsg.error('获取导出进度失败!');
return;
}
if (progressBar == 0) {
//显示内容
//var processText = '总导出数量:' + count + ';已完成数量:' + total + '; ';
var processText = '正在处理,请稍等...... ';
//更新进度条;
msgBox.updateProgress(0, processText, '');
} else if (progressBar != 0) {
if (progressBar == 100) {
//计算进度 progressBar
//显示内容
var processText = '导出完毕! ';
//更新进度条;
msgBox.updateProgress(1, processText, '');
msgBox.hide();
Ext.TaskManager.stop(task);
//win.show();
} else {
//显示内容
var processText = '正在导出...... ';
//更新进度条;
msgBox.updateProgress(progressBar, processText, '');
}
}
},
failure: function (response, opts) {
RMsg.error('导出失败!');
Ext.TaskManager.stop(task);
}
});
}
};
Ext.TaskManager.start(task);
}
后端计算进度条状态代码如下(java):
public String flushProgress(HttpServletRequest request) {
HashMap<String, Object> map = null;
try {
map = new HashMap<String, Object>();
String progressBar = (String) request.getSession().getAttribute("progressBar");//节点状态数据
Integer totleCount = (Integer) request.getSession().getAttribute("totleCount");//总条数
Integer totle = (Integer) request.getSession().getAttribute("totle");//此时处理到多少条
if (StringUtils.isEmpty(progressBar) || "0".equals(progressBar)) {
map.put("failure", false);
map.put("progressBar", 0);
} else if ("100".equals(progressBar)) {
//封装每个节点的状态值给前端
map.put("failure", false);
map.put("progressBar", 100);
request.getSession().removeAttribute("progressBar");
request.getSession().removeAttribute("totleCount");
request.getSession().removeAttribute("totle");
} else if ("-1".equals(progressBar)) {
map.put("failure", true);
} else {
if (totleCount != 0 && totleCount != null && totle != 0 && totle != null) {
map.put("failure", false);
BigDecimal bigDecimal = new BigDecimal(((double) totle / (double) totleCount));
map.put("progressBar", bigDecimal.setScale(2, BigDecimal.ROUND_HALF_UP));
map.put("totle",totle);*/
}
}
} catch (BaseException e) {
map.put("failure", true);
e.buildException("method[flushProgress]", "获取进度失败!");
}
//已jsion字符串返回
return JSON.toJSONString(map);
}
说明
以上只是个人的实现方式,如有不妥的地方,还望大佬指正批评,在此感谢各位!