SpringBoot如何实现一个实时更新的进度条的示例代码

 更新时间:2020年05月28日 09:09:19   作者:听风听雨听世界  
本文详细的介绍了SpringBoot如何实现一个实时更新的进度条,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

前言

博主近期接到一个任务,大概内容是:导入excel表格批量修改状态,期间如果发生错误则所有数据不成功,为了防止重复提交,做一个类似进度条的东东。

那么下面我会结合实际业务对这个功能进行分析和记录。

正文

思路

前端使用bootstrap,后端使用SpringBoot分布式到注册中心,原先的想法是导入表格后异步调用修改数据状态的方法,然后每次计算修改的进度然后存放在session中,前台jquery写定时任务访问获取session中的进度,更新进度条进度和百分比。但是这存在session在服务间不共享,跨域问题。那么换一个方式存放,存放在redis中,前台定时任务直接操作获取redis的数据。

实施

进度条

先来看一下bootstrap的进度条

<div class="progress progress-striped active">
  <div class="progress-bar progress-bar-success" role="progressbar"
     aria-valuenow="60" aria-valuemin="0" aria-valuemax="100"
     style="width: 40%;">
    40%
  </div>
</div>

 进度条更新主要更新style="width: 40%;"的值即可,div里面的40%可以省略,无非时看着明确。

可以考虑将进度条放入弹出层。

定时任务

//点击确认导入执行此方法
function bulkImportChanges() {
  //获取批量操作状态文件
  var files = $("#importChanges").prop("files");
  var changesFile = files[0];
  var formData = new FormData();
  formData.append("importFile",changesFile);
  $.ajax({
    type : 'post',
    url : "/risk/bulk***es",
    data : formData,
    processData : false,   //文件ajax上传要加这两个的,要不然上传不了
    contentType : false,   //
    success : function(obj) {
      //导入成功
      if (obj.rspCode == "00") {
        //定时任务获取redis导入修改进度
        var progress = "";
        var timingTask = setInterval(function(){
          $.ajax({
            type: 'post',
            url: "/risk/t***k",
            dataType : 'json',
            success: function(result) {
              progress = result.value;
              if (progress != "error"){
                var date = progress.substring(0,6);
                //这里更新进度条的进度和数据
                $(".progress-bar").width(parseFloat(date)+"%");
                $(".progress-bar").text(parseFloat(date)+"%");
              }
            }
          });
          //导入修改完成或异常(停止定时任务)
          if (parseInt(progress)==100 || progress == "error") {
            //清除定时执行
            clearInterval(timingTask);
            $.ajax({
              type: 'post',
              url: "/risk/de***ess",
              dataType : 'json',
              success: function(result) {
                $("#bulkImportChangesProcessor").hide();
                if (parseInt(progress) == 100) {
                  alert("批量导入修改状态成功");
                }
                if (progress == "error") {
                  alert("批量导入修改状态失败");
                }
                //获取最新数据
                window.location.href="/risk/re***ByParam" rel="external nofollow" rel="external nofollow" ;
              }
            });
          }
        }, 1000)
      }else {
        $("#bulkImportChangesProcessor").hide();
        alert(obj.rspMsg);
        window.location.href="/risk/re***ByParam" rel="external nofollow" rel="external nofollow" ;
      }
    }
  });
}

解释:点击确认导入文件后成功后开启定时任务每一秒(一千毫秒)访问一次后台获取redis存放的进度,返回更新进度条,如果更新完成或者更新失败(根据后台返回的数据决定)则停止定时任务显示相应的信息并刷新页面。获取最新数据。

后台控制层

/**
 * 退单管理批量修改状态导入文件
 * @param importFile
 * @return
 */
 @ResponseBody
 @RequestMapping("/bulk***es")
 public Map<String,Object> bulk***es(MultipartFile importFile){
   log.info("退单管理批量修改状态导入文件,传入参数:"+importFile);
 Map<String,Object> map = new HashMap<>();
 List<Bulk***esEntity> fromExcel = null;
 try{
      //使用工具类导入转成list
  String[] header = {"sy***um","t***mt","ha***ult","re***nd","sy***nd","r**k"};
  fromExcel = importExcelUtil.importDataFromExcel(importFile, header, BulkImportChangesEntity.class);
  if (fromExcel.size()==0){
  map.put("rspCode","99");
  map.put("rspMsg","导入数据不能为空");
  return map;
  }
 }catch (Exception e){
  map.put("rspCode","99");
  map.put("rspMsg","导入操作表失败,请注意数据列格式");
  return map;
 }
 try {
  //这里会对list集合中的数据进行处理

  log.info("调用服务开始,参数:"+JSON.toJSONString(fromExcel));
  //String url = p4_zuul_url+"/***/ri***eat/bu***nges";
  String url = p4_zuul_url+"/***-surpass/ri***eat/bu***nges";
  String result = HttpClientUtil.doPost(url,JSON.toJSONString(fromExcel));
  log.info("调用服务结束,返回数据:"+result);
  if (result != null){
  map = JSONObject.parseObject(result, Map.class);
  log.info("批量修改状态导入:"+JSON.toJSONString(map));
  }
 }catch (Exception e){
  map.put("rspCode","99");
  map.put("rspMsg","导入操作表失败");
  log.info("bu***es exception",e);
  return map;
 }
 return map;
 }

 /**
 * 获取退单管理批量修改状态导入文件进度条进度
 * @return
 */
 @ResponseBody
 @RequestMapping("/t***sk")
 public Map<String,Object> t***sk(){
 Map<String,Object> map = new HashMap<>();
    //获取redis值
 String progress = HttpClientUtil.doGet(
  p4_zuul_url + "/" + p4_redis + "/redis***ler/get?key=progressSchedule");
 if (progress != null){
  map = JSONObject.parseObject(progress, Map.class);
  log.info("进度条进度:"+JSON.toJSONString(map));
  map.put("progressSchedule",progress);
 }else {
  HttpClientUtil.doGet(
   p4_zuul_url + "/" + p4_redis + "/redis***ler/del?key=progressSchedule");
 }
 return map;
 }

 /**
 * 清除redis进度条进度
 * @return
 */
 @ResponseBody
 @RequestMapping("/de***ess")
 public Map<String,Object> de***ess(){
 Map<String,Object> map = new HashMap<>();
 String progress = HttpClientUtil.doGet(
  p4_zuul_url + "/" + p4_redis + "/redis***ler/del?key=progressSchedule");
 if (progress != null){
  map = JSONObject.parseObject(progress, Map.class);
  log.info("返回数据:"+JSON.toJSONString(map));
 }
 return map;
 }

导入时调用第一个bulk***es方法,定时任务调用t***sk方法,导入完成或发生错误调用de***ess方法删除redis数据,避免占用资源。

服务层

@Async//开启异步
 @Transactional(rollbackFor = Exception.class)//事务回滚级别
 @Override
 public void bulkImportChanges(List<BulkImportChangesParam> list) {
 //初始化进度
 Double progressBarSchedule = 0.0;
 redisClient.set("progressSchedule", progressBarSchedule + "");//存redis
 try {
  for (int i = 1; i <= list.size(); i++) {
  RiskRetreatEntity entity = riskRetreatMapper.selectRetreatListBySysRefNum(list.get(i-1).getSysRefNum());
  if (entity == null){
   //查询结果为空直接进行下次循环不抛出
   continue;
  }
  //实体封装
        ···
        //更新
  riskRetreatMapper.updateRetreatByImport(entity);
  //计算修改进度并存放redis保存(1.0 / list.size())为一条数据进度
  progressBarSchedule = (1.0 / list.size()) * i*100;
  redisClient.set("progressSchedule", progressBarSchedule+"");
  if (i==list.size()){
   redisClient.set("progressSchedule", "100");
  }
  }
 }catch (Exception e){
  //当发生错误则清除缓存直接抛出回滚
  redisClient.set("progressSchedule","error");
  log.info("导入更新错误,回滚");
  log.info("bulkImportChanges exception:",e);
  throw e;
 }
 }

每更新一条数据存放进度,当发生错误则进行回滚。如果开启异步则需要在启动类添加注解@EnableAsync。

@EnableAsync
···//其他注解
public class Application {
  public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
  }
}

结果样式

结尾

这次结合了前端的定时任务,后台事务以及异步,总的来说还是一次🙅‍不错的体验。

到此这篇关于SpringBoot如何实现一个实时更新的进度条的示例代码的文章就介绍到这了,更多相关SpringBoot实时更新进度条内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 详解Lombok快速上手(安装、使用与注解参数)

    详解Lombok快速上手(安装、使用与注解参数)

    这篇文章主要介绍了详解Lombok快速上手(安装、使用与注解参数) ,这里整理了一些日常编码中能遇到的所有关于它的使用详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-12-12
  • Springboot整合freemarker 404问题解决方案

    Springboot整合freemarker 404问题解决方案

    这篇文章主要介绍了Springboot整合freemarker 404问题解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-05-05
  • Java设计模式之共享模式/享元模式(Flyweight模式)介绍

    Java设计模式之共享模式/享元模式(Flyweight模式)介绍

    这篇文章主要介绍了Java设计模式之共享模式/享元模式(Flyweight模式)介绍,本文讲解了为什么使用共享模式/享元模式、如何使用共享模式/享元模式、Flyweight模式在XML等数据源中应用等内容,需要的朋友可以参考下
    2015-03-03
  • Java 数据库连接池详解及简单实例

    Java 数据库连接池详解及简单实例

    这篇文章主要介绍了Java 数据库连接池详解及简单实例的相关资料,需要的朋友可以参考下
    2016-12-12
  • 解决Mybatis-Plus操作分页后数据失效问题

    解决Mybatis-Plus操作分页后数据失效问题

    这篇文章主要介绍了解决Mybatis-Plus操作分页后数据失效问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-11-11
  • 关于activemq安装配置以及启动错误的解决

    关于activemq安装配置以及启动错误的解决

    这篇文章主要介绍了关于activemq安装配置以及启动错误的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-06-06
  • java多线程中断代码详解

    java多线程中断代码详解

    这篇文章主要介绍了java多线程中断代码详解,具有一定参考价值,需要的朋友可以了解下。
    2017-11-11
  • 详解java生成json字符串的方法

    详解java生成json字符串的方法

    本篇文章主要介绍了java生成json字符串的方法,包括map对象转换成json对象,list转换成json,json转换成list和map,有兴趣的可以了解一下。
    2017-01-01
  • JavaPoet的使用指南小结

    JavaPoet的使用指南小结

    这篇文章主要介绍了JavaPoet的使用指南小结,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-10-10
  • 通过Java 程序获取Word中指定图片的坐标位置

    通过Java 程序获取Word中指定图片的坐标位置

    本文介绍通过Java程序获取Word文档中指定图片的坐标位置,程序运行环境是jdk1.8开发环境idea,通过java程序代码给大家介绍的非常详细,需要的朋友参考下吧
    2021-05-05

最新评论