Bootstrap

Java实现实时进度查询功能

在查询大量数据或使用第三方查询数据时,数据量较大、查询效率较低,往往在前端点击查询按钮后需要等待很久,也无法获取到查询进度,所以,我们可以根据redis缓存来实现实时进度查询+显示上次查询时间的功能+同一时间只允许一人查询功能。

页面

在不查询的时候,页面时这样子的

 点击查询后,出现查询进度并实时更新,按钮置为灰色

查询完毕后,更新时间

后端

实现功能

实时缓存查询进度

查询完毕显示上次查询时间

同一时间只允许一人查询

public void select() {
    String checkStatus = jedisclient.get(myKey);
    //如果发现在进度中,说明有人正在查询,直接返回
    if (checkStatus != null && checkStatus.contains("Progress")){
        return;
    }
    //获取需要查询的数据
    List<String> userIds = userMapper.selectAll();
    //如果需要更新的数据量为零,直接写入时间戳,作为上次查询时间
    if (userIds == null || userIds.size() == 0){
        jedisclient.set(myKey, Integer.toString(system.currentTimeMillis()));
        return;
    }
    //异步查询
    ThreadPoolUtil.doExecutor(()->{
        int total = userIds.size();
        int pageNum = 0;
        //分页查询
        while (pageNum <= total){
            List<String> ids = userIds.subList(pageNum, Math.min(pageNum+20, total));
            ids.forEach(id -> {
                //第三方查询操作 或 查询数据库
            });
            //实时更新查询进度
            jedisclient.set(myKey, "Progress:" + Math.round(pageNum * 100 / total) + "%");
            pageNum += 20;
        }
        //查询完毕,设置时间戳,作为上次查询时间
        jedisclient.set(DISPUTE_REFRESH_CHECK_STATUS, Integer.toString(YamiDateUtil.get_LA_Second()));
    });
}

//提供一个接口来实现获取redis缓存
public String getCheckStatus(){
	return jedisclient.get(DISPUTE_REFRESH_CHECK_STATUS);
}

前端

实现功能

内容实时刷新到在页面

在查询时,显示进度

在不查询时,显示按钮和上次查询时间

我用的是AngularJS,代码写了个大概,主要提供思路

//首先实现一个初始化任务,页面打开就执行,用来初始化页面上要显示的上次更新时间
$scope.$watch('$viewContentLoaded', function() {
    //写一个定时器,每2秒执行一次getCheckStatus方法
    //在初始化页面的时候,就开始循环查询redis缓存
    interval = setInterval(getCheckStatus, 1000);
});

//再写一个方法,用户点击之后执行
vm.select= function () {
    //发送http请求,调用后端方法,进行查询
    disputeService.select();
    //点击这个方法的时候也要执行定时器,每两秒调用一次方法,用来实时更新进度
    interval = setInterval(getCheckStatus, 1000);
};

//查询redis缓存的方法
function getCheckStatus() {
    //发送http请求,调用后端方法,获取redis缓存
    disputeService.getCheckStatus().success(function (data){
        if (data.body.charAt(0)==='P') {
            //如果redis缓存是进度,设置i为0,不结束定时器
            checkProgress = data.body;
            isUsed = true;
            i = 0;
        } else {
            //如果redis缓存是时间,将时间格式化,并表现在页面
            checkTime = moment(data.body * 1000).format("MM-DD HH:mm");
            isUsed = false;
            i++;
            //五次查询缓存都是时间,就关闭定时器
            if (i === 5){
                clearInterval(interval);
            }
        }
    });
}
;