SpringBoot如何实现⼀个实时更新的进度条
前⾔
博主近期接到⼀个任务,⼤概内容是:导⼊excel表格批量修改状态,期间如果发⽣错误则所有数据不成功,为了防⽌重复提交,做⼀个类似进度条的东东。
那么下⾯我会结合实际业务对这个功能进⾏分析和记录。
正⽂
思路springboot实现热部署
前端使⽤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"
>
40%
</div>
</div>
进度条更新主要更新的值即可,div⾥⾯的40%可以省略,⽆⾮时看着明确。
可以考虑将进度条放⼊弹出层。
定时任务
/
/点击确认导⼊执⾏此⽅法
dockerfile命令详解
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";
}
});
}
},1000)
}else{
$("#bulkImportChangesProcessor").hide();
alert(obj.rspMsg);
window.location.href="/risk/re***ByParam";
}
}
});
}
解释:点击确认导⼊⽂件后成功后开启定时任务每⼀秒(⼀千毫秒)访问⼀次后台获取redis存放的进度,返回更新进度条,如果更新完成或者更新失败(根据后台返回的数据决定)则停⽌定时任务显⽰相应的信息并刷新页⾯。获取最新数据。
后台控制层
/**
* 退单管理批量修改状态导⼊⽂件
* @param importFile
sql语句高级面试题
* @return
*/
@ResponseBody
jquery下载文件进度条@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("调⽤服务开始,参数:"+JSONString(fromExcel));
//String url = p4_zuul_url+"/***/ri***eat/bu***nges";
String url = p4_zuul_url+"/***-surpass/ri***eat/bu***nges";
String result = HttpClientUtil.doPost(JSONString(fromExcel));
log.info("调⽤服务结束,返回数据:"+result);
if(result != null){
map = JSONObject.parseObject(result, Map.class);
log.info("批量修改状态导⼊:"+JSONString(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("进度条进度:"+JSONString(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("返回数据:"+JSONString(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.(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);
}
}
结果样式
结尾
这次结合了前端的定时任务,后台事务以及异步,总的来说还是⼀次 不错的体验。
优秀的代码只能通过时间的冲刷才会显现的

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。