java-關於進度條
阿新 • • 發佈:2018-11-07
【背景】
因為公司業務中需要有批量處理訂單,因為訂單量比較大,操作人員要等待比較久,可能他不知道後臺是否在執行,還是後臺宕機,所以考慮做一個進度條,這樣對操作人員比較友好。
【採用技術】
bootstrap,jQuery
【方案】
用一個類封裝進度條狀態,total,success_num,fail_num,isfinished
用一個靜態的Map,儲存進度條狀態物件(因為一個物件就是一個任務,隔離開每個物件,防止類似2個人對同一物件操作),每個任務一個物件,這邊的key是前端生成的uuid傳到後臺的,本來可以通過執行緒來執行service,然後用Thread_id來儲存該物件,因為thread_id不好傳到前端,因此作廢。
然後用一個ProgressUtil用來操作靜態的Map。
主要邏輯:後臺執行核心service時,不斷修改進度條狀態的屬性,然後前端通過定時器不斷髮送請求獲取進度條狀態物件,若返回物件isfinished=true,就清除定時器,後臺靜態Map也要刪除該物件,因為靜態Map會不斷膨脹導致記憶體不夠
【程式碼】
public class Progress implements Serializable { //記錄的總條數 private Integer total = 0; //成功的記錄條數 private Integer success_num = 0;//失敗的記錄條數 private Integer fail_num = 0; //執行是否結束 private boolean isfinished = true; public Integer getTotal() { return total; } public void setTotal(Integer total) { this.total = total; } public Integer getSuccess_num() { return success_num; }public void setSuccess_num(Integer success_num) { this.success_num = success_num; } public Integer getFail_num() { return fail_num; } public void setFail_num(Integer fail_num) { this.fail_num = fail_num; } public boolean isIsfinished() { return isfinished; } public void setIsfinished(boolean isfinished) { this.isfinished = isfinished; } }
public class ProgressUtil { //每個執行緒儲存進度狀態的map public static Map<String,Progress> progressMap = new HashMap<>(); public static Progress getProgress(String uuid){ if(!progressMap.containsKey(uuid)){//若progress不存在 return new Progress(); } return progressMap.get(uuid); } public static void setProgress(String uuid,Progress progress){ progressMap.put(uuid,progress); } public static Progress delProgress(String uuid){ return progressMap.remove(uuid); } }
@Controller @RequestMapping("/testjindutiao") public class Jindutiao2Controller { public static final String[] data = new String[100]; //模擬處理service的http請求 @RequestMapping("/testservice.do") @ResponseBody public String testservice(@RequestParam("uuid")String uuid){ service(uuid); return "ok"; } //模擬service處理 public void service(String uuid) { Progress progress = ProgressUtil.getProgress(uuid); progress.setIsfinished(false); progress.setTotal(data.length); for(int i=0;i<data.length;i++){ if(i/2==0){ progress.setFail_num(progress.getFail_num()+1); // Thread.sleep(500); }else{ progress.setSuccess_num(progress.getSuccess_num()+1); // Thread.sleep(500); } System.out.println("正在處理第"+(i+1)+"條記錄"); //每次改變都要存進去 // JindutiaoController.jindutiaoMap.put(uuid,map); if(i==data.length-1){ progress.setIsfinished(true); } ProgressUtil.setProgress(uuid,progress); } } //模擬獲取進度條的請求 @RequestMapping("/getjindutiao.do") @ResponseBody public Progress getjindutiao(@RequestParam("uuid")String uuid){ Progress progress = ProgressUtil.getProgress(uuid); if(progress.isIsfinished()){ ProgressUtil.delProgress(uuid); } return progress; } }
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> <link rel="stylesheet" href="/theme/lte/assets/bootstrap/css/bootstrap.min.css"> </head> <body> <div class="container"> <input type="text" id="uuid"> <div style="margin-top: 200px"> <div class="progress"> <div class="progress-bar" style="width:0%;" role="progressbar" aria-valuenow="30" aria-valuemin="0" aria-valuemax="100" id="progress"> </div> </div> <div> <span style="color:red">失敗<span id="fail_num">0</span>條</span> </div> <button class="btn-sm btn-primary" id="start">執行</button> </div> </div> </body> <!-- jQuery--> <script src="/theme/lte/assets/plugins/jQuery/jQuery-2.1.4.min.js"></script> <!-- bootstrap--> <script src="/theme/lte/assets/bootstrap/js/bootstrap.min.js"></script> <script src="/js/virtualcard/testjindutiao.js"></script> </html>
$(function(){ $('#uuid').val(getUUID()); $('#start').on('click',testjindutiao); }); function getUUID() { return 'xxxx-xxxx-xxxx-xxxx-xxxx'.replace(/[xy]/g, function(c) { var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8); return v.toString(16); }).replace(/\-/g,""); } var testFileTimer; function testjindutiao(){ var uuid = $('#uuid').val(); $.ajax({ url:"/testjindutiao/testjindutiao.do?uuid="+uuid, type:"post", success:function(res){ console.log(res); } }); testFileTimer = setTimeout(loadProcess, 200); } function loadProcess() { var uuid = $('#uuid').val(); $.ajax({ url: "/testjindutiao/getjindutiao.do?uuid="+uuid, type: 'post', success: function (data) { load_progress(data); if(data.isfinished){ clearTimeout(testFileTimer); }else{ testFileTimer = setTimeout(loadProcess ,200); } } }) } function load_progress(data){ var total = data.total; var success_num = data.success_num; var fail_num = data.fail_num; $('#fail_num').html(data.fail_num); $('#progress').css("width",((success_num/total)*100)+'%'); $('#progress').html(success_num+'/'+total); }