導出時間進度條設計流程
對於在企業一般的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);
}
說明
以上只是個人的實現方式,如有不妥的地方,還望大佬指正批評,在此感謝各位!