數據導入與實時進度條實現

                                   digiflow數據導入與實時進度條實現

 

本文檔只是稍微解析下數據導入的流程,以及講解實時進度條實現方法

 

數據批量導入流程

1、客戶把.txt數據打包成.gz文件,發給我們。

GZ文件格式,每個文件的第一行是唯一的數據,導入完成後要插入到ImportRecord

名字格式:DigiFlow_南寧 - 平安出單中心_20100201_000100ECHW8P8708.txt

內容格式:以”||”爲分割符

比如:00||000100ECHW8P8708||8||18:08:17

00代表表名稱

000100ECHW8P8708 代表這個文件的唯一標識

 

2JAVA解壓縮GZ文件

JAVA提供了GZIPInputStream 解壓API,把裏面的內容寫入到txt文件裏。

 

3、解壓的文件臨時存放目錄

一種是在安裝的TOMCAT根目錄下新建file目錄,然後System.getProperty("user.dir") + "/file/"

二種是System.getProperty("java.io.tmpdir")得到的是tomcat臨時目錄

項目中用到的是第一種

 

4讀取解壓的文件

if("00".equals(fileinfos[0]))  讀取到第一行時,根據UID判斷是否導入過該文件。如果導入過則系統提示,並刪除解壓的文件。如果沒有導入過,則繼續執行下一步直到導入完成,完成後再插入這個文件的唯一標識。如:000100ECHW8P8708

 

讀取到其他行時,獲取其UID,判斷是否插入過該記錄。如果插入過,則執行update。如果沒插入過,則執行insert.

 

5、拼SQL實現方式實現DMLinsertupdate

程序中的insertupdate語句是獲得文件的中的列名之後,通過表名和列明去查找相應的字段信息,有的字段是varcharchardatetime型則加上‘’號。詳細參見源碼bossdataimportBusinessDAOImpl.java類的getStringType()方法。

 

 

 

 

AJAX實現實時WEB進度條

我們爲了改善用戶界面,通常會在處理量大或者是網絡速度較慢的時候,給用戶顯示一個處理進度,讓用戶心理有底,增強用戶等待結果的耐心,以改善用戶體驗。爲了達到這個效果,通常做法有兩大類:簡單等待和真實的處理進度,本文着重討論第二種方法的實現。

 

1)簡單的等待界面:這種做法之所以說簡單,就是在用法發送了處理命令後,立即在頁面的某個地方替換一個waiting的圖片,比如一個轉圈的GIF,一張Loading的圖片等,這種不稱之爲進度條,頂多就是個等待條,但通常還是可以給用戶帶來那麼點滿足,在業務量不大的情況下,也夠用了,例子參見http://www.belitastone.com的首頁。

 

2)真實的等待進度:比如說,我要在B/S系統中實現一個數據導入的功能,數據文件總共有100個,每個文件包含成千上萬的數據,導入過程可能需要15分鐘,那麼我還用一個圖片在那邊打轉嗎?現在這樣還是不夠的,我可能需要讓使用者知道,我當前處理的是第幾個文件,還剩下幾個,處理的百分比,並顯示一個加載的真實進度條,這個進度條要如實反映處理的百分比。

 

實現1:由於用戶處理的數據量大,可以在文件導入過程中,循環計算進度,並將進度信息存儲在上下文中,並在前臺頁面定時從上下文讀取進度數據,並在頁面顯示。這種方法思路比較直接。

 

實現2:使用觀察者模式,實現進度主動通知。思路是:在文件導入過程中,計算進度信息,並將進度數據通知給觀察者,前臺頁面定時向觀察者諮詢進度,並將進度顯示到頁面中。

 

本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/zhengtanyun/archive/2009/07/06/4325528.aspx

 

 

我來說下我的實現方式

關於他說的“實現1”,說把進度信息存儲到上下文,這個貌似有問題,這個上下文是servlet上下文?據我所知,上下文作用域和Application作用域一樣大,進度條每個用戶執行不同的導入操作,存到上下文做什麼,還不亂套?

 

我的實現方式和“實現2”有點像。思路是:在文件導入過程中,循環計算進度信息,並將進度數據放入SESSION,前臺頁面通過AJAX定時調用,獲取進度,並將進度顯示到頁面中.

進度數據有:總的數據量、已導入數據量、已經上傳時間。

 

另外一種情況:當正在進行導入時,點擊了別的頁面,從而頁面上的進度條就沒有了,而後臺卻還在運行。有幾種方法,一是彈出模式對話框,在模式框裏面進行導入,但是這樣還有點麻煩。二是當用戶點擊了別的頁面再回到導入頁面時,又重新讀取SESSION中的進度信息。這需要在ACTION中設置一個全局變量來作爲是否正在執行導入操作的標記。

 

 

 

最終效果圖:(見附件) 

 效果圖

 

 

代碼實現參考源代碼manage中的DigimpAction.java以及dimpImport.jsp

核心代碼如下:

ACTION 部分代碼

//	讀取數據導入實時狀態
	public ActionForward doStatus(ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response) throws Exception
	{
		// 設置該響應不在緩存中讀取
		response.addHeader("Expires", "0");
		response.addHeader("Cache-Control",
				"no-store, no-cache, must-revalidate");
		response.addHeader("Pragma", "no-cache");
		response.setHeader("Cache-Control", "no-cache");
		response.setCharacterEncoding("utf-8");          
	    response.setContentType("text/html; charset=utf-8");          
		int totalSize = 0;// 總數據的條數
		int bytesRead = 0;// 已導入數據條數
		long getElapsedTimeInSeconds=0;// 獲得已經上傳得時間
		HttpSession session = request.getSession(false);
        if (session.getAttribute("TOTALSIZE")  != null) {
        	if(count == 0){
        		session.removeAttribute("TOTALSIZE");
        	}else{
        		totalSize=Integer.parseInt(session.getAttribute("TOTALSIZE").toString());
            	
        	}
        }
        if (session.getAttribute("BYTESREAD")  != null) {
        	if(count == 0){
        		session.removeAttribute("BYTESREAD");
        	}else{
        		bytesRead=Integer.parseInt(session.getAttribute("BYTESREAD").toString());
        	}
        }
        if (session.getAttribute("STARTTIME")  != null) {
        	long stime=Long.parseLong((String)session.getAttribute("STARTTIME"));
        	getElapsedTimeInSeconds=(System.currentTimeMillis() - stime) / 1000;
        }
		
		//計算上傳完成的百分比
        String percentComplete="0";
        if(totalSize > 0){
        	double k = (double)bytesRead/totalSize*100; 
        	BigDecimal big=new BigDecimal(k);  
        	percentComplete = big.setScale(2,BigDecimal.ROUND_HALF_UP).toString(); 
        }
		//獲得上傳已用的時間
		long timeInSeconds = getElapsedTimeInSeconds;
		//計算平均上傳速率
		//double uploadRate = bytesRead / (timeInSeconds + 0.00001);
		//System.out.println("**************計算平均上傳速率="+bytesRead);
		// 計算總共所需時間
		//double estimatedRuntime = totalSize / (uploadRate + 0.00001);
		
		//將上傳狀態返回給客戶端
		response.getWriter().println("<b>Import Status:</b><br/>");
		if (bytesRead != totalSize) {
			response.getWriter().println(
					"<div class=\"prog-border\"><div class=\"prog-bar\" style=\"width: "
							+ percentComplete + "%;\"></div></div>");
			response.getWriter().println(
					"Imported: " + bytesRead + " out of " + totalSize
							+ " Records (" + percentComplete + "%) <br/>");
			response.getWriter().println(
					"Runtime: " + formatTime(timeInSeconds) + " <br/>");
		} else {
			response.getWriter().println(
					"Imported: " + bytesRead + " out of " + totalSize
							+ " Records<br/>");
			response.getWriter().println("Complete.<br/>");
		}
        //如果文件已經導入完畢
		if (bytesRead == totalSize) {
			response.getWriter().println("<b>Imported complete.</b>");
		}
		return null;
	}
	private String formatTime(double timeInSeconds) {
		long seconds = (long) Math.floor(timeInSeconds);
		long minutes = (long) Math.floor(timeInSeconds / 60.0);
		long hours = (long) Math.floor(minutes / 60.0);

		if (hours != 0) {
			return hours + "hours " + (minutes % 60) + "minutes "
					+ (seconds % 60) + "seconds";
		} else if (minutes % 60 != 0) {
			return (minutes % 60) + "minutes " + (seconds % 60) + "seconds";
		} else {
			return (seconds % 60) + " seconds";
		}
	}
	//頁面調用此方法,檢查導入工作是否正在進行時,0:無 1:正在進行
	public int checkImportStatus(){
		return count;
	}

 

 

 

 

dimpImport.jsp  部分代碼

<script type="text/javascript">
	var xmlHttp; 
	function createXMLHttpRequest()//創建XMLHttpRequest對象 
	{ 
		if(window.ActiveXObject){ 
			xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); 
		}else if(window.XMLHttpRequest){ 
			xmlHttp = new XMLHttpRequest(); 
		} 
	} 
    //導入程序入口
	function tijiao(){
	    document.forms[0].action=" ";
		document.forms[0].submit();
		go();
	}
	function go() 
	{
		createXMLHttpRequest();//創建XMLHttpRequest對象
		xmlHttp.onreadystatechange = callBack;//設置回調函數 
		var url = "digimp.do?method=doStatus";//請求的地址 
		var button = document.getElementById("go"); 
		button.disabled = true;//設置按鈕不可用 
		xmlHttp.open("post",url,true);//打開對服務器的連接 
		xmlHttp.send();//發送請求 
	} 
	function callBack() 
	{ 
		if(xmlHttp.readyState == 4){ 
			if(xmlHttp.status == 200){
				setTimeout("go()",500);//定時調用
				document.getElementById('status').innerHTML =xmlHttp.responseText;
			} 
		} 
	}
	//檢查是否有正在進行的導入操作
	function page_init(){
		DigimpAction.checkImportStatus(function callback_init(data){
			if(data != '0'){
				document.getElementById("go").disabled = true;
				go();
			}else{
				document.getElementById("go").disabled = false;
			}
		});
	}
	
</script>
<body onload="page_init();">
    	<!-- 這裏顯示進度條 -->
<div id="status"></div>
</body>

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章