jsp實時顯示后台批處理進度 - out分塊,簡單的長連接方式


這兩天在實現一個批處理操作,但是想讓前台實時顯示后台批處理進度,本想着用復雜一些的框架可以實現異步信息調用

但是鑒於是內部管理系統,且只有一兩個人用到這個功能,所以做了一個簡單的長連接方式的實時響應

 

有些人說使用ajax請求,定時刷新,個人覺得很耗服務器資源,而且准確的說也不是實時的

【原文摘自 BearRui(AK-47) 的Bloghttp://www.blogjava.net/BearRui/archive/2010/06/01/ajax_better_experience.html

 

使用技術:AJAX - onreadystatechange 事件

  詳細解釋:http://www.runoob.com/ajax/ajax-xmlhttprequest-onreadystatechange.html

  MSDN:https://msdn.microsoft.com/en-us/library/ms535874(VS.85).aspx

 

要解決實現上面的功能,需要解決下面幾個問題:

   1. 服務器如何在處理一部分數據后傳遞部分response到瀏覽器。

   2、瀏覽器如何能處理服務器傳遞過來部分數據,並保持http連接直到處理完全完畢。

 

解決

  第1個問題,使用flush讓response分塊進行呈現就可以了,具體請參考我另一遍隨筆"flush讓頁面分塊,逐步呈現 http://www.blogjava.net/BearRui/archive/2010/05/19/flush_chunk_encoding.html";

  第2個問題,則需要用到XMLHttpRequest的readyState狀態,w3c對 readyState 定義如下幾個值:

  UNSENT = 0; // 沒有發送請求

  OPENED = 1;    // 已經打開http連接

  HEADERS_RECEIVED = 2; // 接收到response header

  LOADING = 3;          // 真正接收response body   

  DONE = 4;             // 請求接收完畢

另外的問題: readyState每次返回0-4的狀態時,state的值是多少呢?200嗎?還是其他?

  首先,status是XMLHttpRequest對象的一個屬性,表示響應的HTTP狀態碼。

 

  在HTTP1.1協議下,HTTP狀態碼總共可分為5大類,如下表所示:

 

 

  1XX    服務器收到請求,需要繼續處理。例如101狀態碼,表示服務器將通知客戶端使用更高版本的HTTP協議。 

 

  2XX    請求成功。例如200狀態碼,表示請求所希望的響應頭或數據體將隨此響應返回。 

 

  3XX    重定向。例如302狀態碼,表示臨時重定向,請求將包含一個新的URL地址,客戶端將對新的地址進行GET請求。 

 

  4XX    客戶端錯誤。例如404狀態碼,表示客戶端請求的資源不存在。 

 

  5XX    服務器錯誤。例如500狀態碼,表示服務器遇到了一個未曾預料的情況,導致了它無法完成響應,一般來說,這個問題會在程序代碼出錯時出現。

 

  其次,經過測試,每次readyState有狀態變化,如果后台不異常,那么返回都是200,所以當readyState返回4時候,需要對state=200做判斷,否則提示批處理異常

 

下面來看代碼

 

 

 

    ===================前端代碼====================

    //打開框
    $('#settle-batch').dialog("center");
    settleBatch.html("");
    $('#settle-batch').dialog('open').dialog('setTitle', "批量處理進度顯示");

    //發送批處理請求
    var xhr = new window.XMLHttpRequest();
    if(!window.XMLHttpRequest){
        try {
            xhr = new window.ActiveXObject("Microsoft.XMLHTTP");
        } catch(e) {
            alertMsg("失敗", "創建請求失敗,請重試");
        }
    }
    xhr.open("post","http://localhost:8081/WMS/agentsettle/batch");
    settleBatch.append("<p>正在發送批處理請求 ...</p>");

    //處理實時回調信息
    var oldSize=0;
    xhr.onreadystatechange = function(){
        var readyState = xhr.readyState;
        //成功發送請求
        if(readyState == 2){
            settleBatch.append("<p>啟動上月代理分成批處理</p>");
            settleBatch.append("<p style='margin: 10px;'></p>");
        }
        //接收事實數據
        if(readyState > 2){
            var tmpText = xhr.responseText.substring(oldSize);
            oldSize = xhr.responseText.length;
            if(tmpText.length > 0 ){
                // 設置文本
                var str = tmpText.replace(/"/g, "");
                settleBatch.append("<p>" + str + "</p>");
            }
        }
        //處理成功
        if(readyState == 4){
            settleBatch.append("<p style='margin: 10px;'></p>");
            if (xhr.status === 200) {
                settleBatch.append("<p>批處理完成 !!!</p>");
            } else {
                settleBatch.append("<p>批處理異常結束 !!!???</p>");
            }
        }
    }
    xhr.send(null);

 

 

 

           =============后台代碼==================
    
            response.setHeader("Content-Type","application/x-javascript");
            //設置out的字符編碼,否則到前台可能中文亂碼
            response.setCharacterEncoding("UTF-8");
            PrintWriter out = getResponse().getWriter();

            Thread.sleep(1000);
            out.println("正在處理第1個 ...");
            out.flush();

            Thread.sleep(1000);
            out.println("正在處理第2個 ...");
            out.flush();

            Thread.sleep(1000);
            out.println("正在處理第3個 ...");
            out.flush();

            Thread.sleep(1000);
            out.println("正在處理第4個 ...");


經測試,現在chrome、firefox、360瀏覽器都支持readyState=3的處理

  基於Webkit的瀏覽器支持的不是很好,需要設置Content-Type:application/x-javascript才行(經測試發現Content-Type:text/html在有些情況下正常,有些情況下又不正常,而用application/x-javascript都正常)。

 

另外方法

1、jquery 1.5已經支持onreadysatechange,可以使用

2、有些 消息異步通訊 的框架也可以實現這樣的功能,不過要看實現實時顯示的功能復雜度

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM