Java Web - Make a simple Wait ProgressBar By Server Response Data

一般在進行網頁操作的時候,某些功能會需要等待Server的處理,如匯入、匯出資料等,當下

有可能會因為資料過多,導致需要處理一段時間,因此有必要去呈現目前的處理進度,以此

使用者才可能知道還需要等多久及網頁有正常在運作。

在這邊將實作一個簡單的等待處理Bar,原理很單純,當使用者點擊按鈕的當下,Server端將

分成兩個處理程序,一個為獨立的執行緒,表示資料處理;而另一頭將製作一個迴圈來等待

,每兩秒跳出迴圈回傳目前Server資料處理的進度,在回傳的資料中會包含是否已處理完畢

及目前的處理的數量,以此更新前端Ext MessageBox的訊息!

接著,再次send request to server side 進行迴圈檢查處理狀態!  因此,以這個例子而言,將會一

直在send request 及 response text,算是一個很陽春、有點愚蠢的方式,有待更好的方法來改

善orz

PS. 若在兩秒的等待中,資料已處理完畢會提前跳出迴圈!

Client: ExtJS

在這邊前端的MessageBox乃是利用JavaScript程式庫來呈現,相關code如下:

var start = "";
function execProcess(){
 if(start == ""){
     Ext.MessageBox.show({
               title:"訊息",
               msg:"處理中...",
               progress:true,
               width:300,
               closable:true
            });
 }
 Ext.Ajax.request({
    url:'<%=request.getContextPath()%>/ProgressServlet',
    params:{isStart: start},
    method: 'POST',
    success: function ( result, request ) {
       var action = Ext.decode(result.responseText);
       var msg = action.result.info;
       var msg_sp = msg.split(":");
       start = msg_sp[1];
       p = parseInt(msg_sp[0])/30;
       var progress_msg = Math.round(100*p)+"% completed";
       if(action.result.success){
          Ext.MessageBox.updateProgress(p, progress_msg, "處理完畢!");
          setTimeout("Ext.MessageBox.hide()",2000);
       }else{
          Ext.MessageBox.updateProgress(p, progress_msg, "處理中...");
          execProcess();
       }
    },
    failure: function ( result, request) {  
       var action = result.responseText;
       Ext.MessageBox.alert('Failed', action.result.info||''); 
    }
      });
}

劇情為按下按鈕後,首先利用全域變數start來判斷MessageBox的初始化,再來向Server端

送出請求,當得到回應後,由回應的JSON CODE來判斷是否已處理完畢,若否則再呼叫自

己重新送出請求!

PS. 在此已將處理的資料總數設為hard code

Server : Java

後端程式碼部分,如下:

MyThread t = null;
...
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws Exception {

JSONObject response_text = new JSONObject();
JSONObject response_info = new JSONObject();
String isStart = request.getParameter("isStart");
int waitSec = 0;
if(isStart.equals("")){
   t = new MyThread();
   t.start();
   isStart = "N";
}
System.out.println("Enter wait.....");
try {
   while(!t.isEnd()){
      try{
         Thread.sleep(1000);
         waitSec++;
         if(waitSec == 2)break;
      } catch(Exception e){
         e.printStackTrace();
      }
   }
   System.out.println("Leave wait.....");
   response_info.put("info", t.getCount()+":"+isStart);
   response_info.put("success", t.isEnd());
   response_text.put("result", response_info);
} catch (JSONException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
}
response.getWriter().print(response_text.toString());
}

首先,當得到client傳過來的參數來進行Thread的初始化,並執行資料處理,因此在下一次的

request時,就不會再進行這一段code。接著,進行等待的部分,檢查目前資料的處理狀態,

當設定的等待時間已過,則回傳相關資料給client,進行處理進度資料的更新!

MyThread部分
class MyThread extends Thread{
   private int count;
   private boolean isEnd;
 
   public boolean isEnd() {
      return isEnd;
   }

   public void setEnd(boolean isEnd) {
      this.isEnd = isEnd;
   }

   public int getCount() {
      return count;
   }

   public void setCount(int count) {
      this.count = count;
   }

   public void run(){
      try{
         while(true){
            count++;
     System.out.println("Execute process is:"+count);
     Thread.sleep(1000);
     if(count == 30){
        isEnd = true;
        break;
     }
  }
       } catch(Exception e){
    e.printStackTrace();
       }
   }
}

在這邊,資料的需要處理的數量是寫死的,若是碰到真實的例子就需要做一些修改囉!

DEMO





總結:

這個例子純粹只是測試用,其方法應該算是最直覺的方式,並沒有什麼可取之處,若有更好

的處理方式請不吝指教囉!

留言