【背景】
因为公司业务中需要有批量处理订单,因为订单量比较大,操作人员要等待比较久,可能他不知道后台是否在运行,还是后台宕机,所以考虑做一个进度条,这样对操作人员比较友好。
【采用技术】
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); }