1. 程式人生 > >java-關於進度條

java-關於進度條

【背景】

因為公司業務中需要有批量處理訂單,因為訂單量比較大,操作人員要等待比較久,可能他不知道後臺是否在執行,還是後臺宕機,所以考慮做一個進度條,這樣對操作人員比較友好。

【採用技術】

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);
}