解决进度条实时数据展示问题

就进度条的实时展示问题,我先前浏览了大量的解决办法,总结出来一共两种解决方案:

  1. 利用session解决,但是使用session无法使用在前后端分离的项目,同时session的存取在不同的api接口中也存在取不到值的问题。
  2. 利用redis(或者其他的第三方分布式存储方式)解决,接下来我将对此方案进行详细的说明。

实际场景:
以批量导入数据为业务场景
实现思路:
编写一个计算进度条信息的统计方法类(类里面包括:进度信息计算、以及redis存储),然后利用循环进行调用该方法,这样就会不断的更新redis里面存储的进度条信息;新写一个api接口用于前台请求redis里面的进度条信息,然后前台使用轮询的方式不断请求api接口,从而实现前台进度实时展示。
实现代码:

  • 计算方法公共类
@Component
public class ProgressLister {

    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * @param beginT  开始时间
     * @param allSize 完整大小
     * @param upSize  已完成大小
     * @param item    进度条序列号
     * @ClassName: ProgressLister
     * @Description: 获取当前进度
     * @Return: void
     */
    public void getProgress(long beginT, long allSize, long upSize, String item) {
        // 当前时间
        long curT = System.currentTimeMillis();
        // 已用时间
        long useTime = curT - beginT;
        // 速度
        String speed = "0";
        String percent = "0";
        if (useTime != 0) {
            speed = rountStr(String.valueOf((allSize * 1.0) / (useTime / 1000)));
        }
        // 当前进度
        if (allSize != 0) {
            percent = rountStr(String.valueOf(((upSize * 1.0) / allSize) * 100));
        }

        // 将进度更新到redis中
        HashOperations<String, Object, Object> opsForHash = redisTemplate.opsForHash();
        opsForHash.put("progress" + item, "speed", speed);
        opsForHash.put("progress" + item, "percent", percent);
    }

    /**
     * @param str
     * @ClassName: ProgressLister
     * @Description: string类型数值只取整数(即小数点之前的值)
     * @Return: java.lang.String
     */
    public String rountStr(String str) {
        String split = new String();
        if (str.contains(".")) {
            split = str.split("\\.")[0];
        }
        return split;
    }
}

  • 刷新进度信息API接口
@Controller
@RequestMapping(value = "/progress")
public class ProgressController {

    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * @param item  进度条序列号
     * @ClassName: ProgressController
     * @Description: 用于刷新进度条信息
     */
    @ResponseBody
    @RequestMapping(value = "/flushProgress")
    public Map<String,Object> flushProgress(String item) throws AppException {
        HashOperations<String, Object, Object> opsForHash = redisTemplate.opsForHash();
        Map<String,Object> map = new HashMap<>();
        Object o = opsForHash.get("progress" + item, "percent");
        String percent = "0";
        if (o != null) {
            percent = o.toString();
        }
        // 当导入完成时,删除redis的值
        if (percent.equals("100")) {
            opsForHash.delete("progress" + item, "speed", "percent");
        }
        map.put("percent", percent);
        return map;
    }
}

  • 实际循环调用
// 使用前需要先添加依赖
@Autowired
private ProgressLister progressLister;

// 用于记录开始时间,大部分是直接在循环之前定义,可以根据自己的实际逻辑使用
long beginT = System.currentTimeMillis();

// 在循环内部使用,用于记录当前进度信息,每次循环时都进行记录
progressLister.getProgress(beginT, zsLenth, i + 1, item);
  • 前端轮询请求
// 创建轮询方法,注意:这里的intervalId是定义轮询后得到的一个轮询序号(即ID号),这里需要注意intervalId的作用域,尽可能使用全局变量(避免因为作用域问题导致轮询无法关闭)
 var intervalId = setInterval(function () {
 	  // item是进度条序列号,主要用于不同的进度条同时进行展示时,区分不用的数据
      $.get('/progress/flushProgress', {item: item}, function (res) {
        // 这里放更新进度条数据的代码,此处省略.........
        // 这里放更新进度条数据的代码,此处省略.........
        
        // 当进度为100时结束轮询,并做一系列的后续操作
        if (res.percent == 100) {
          closeInterval()
        }
      })
    }, "100");

// 用于停止轮询
function closeInterval() {
	clearInterval(intervalId);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值