欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

java实现异步导出数据

程序员文章站 2022-03-16 21:38:29
问题概述:使用java作为后台语言,用poi导出数据时无法异步导出,当数据量稍微大点,就会出现页面傻瓜式等待 (点击导出后,页面无任何反应和提示,还以为此功能无效。然则几秒后浏览器才响应。)这样体验非...

问题概述:

使用java作为后台语言,用poi导出数据时无法异步导出,当数据量稍微大点,就会出现页面傻瓜式等待 (点击导出后,页面无任何反应和提示,还以为此功能无效。然则几秒后浏览器才响应。)这样体验非常 不好。

解决办法:

很简单,将下载数据分离为一个单独方法。在触发导出后,先获取并封装数据(数据量大的话这个过程正好给页面做一个等待框,提示正在下载数据),完成后给前台返回一个状态,当前台收到返回正确返回状态后再关闭等待框并调用下载方法。

demo:

1、获取并封装数据

@requestmapping("exportexcel") //用户数据导出
 public void exportexcel(httpservletrequest request, httpservletresponse response) {
 map<string,object> map = new hashmap<string,object>();
 try{
  equipmentaccident search=(equipmentaccident) 
  request.getsession().getattribute("equipmentaccident1"); //获取保存在session中的查询条件
  if(search !=null ){
  if(str.isnotnull(search.getname())){ //名称
  map.put("name", search.getname());
  }
  if(str.isnotnull(search.getremark())){ //备注
  map.put("remark", search.getremark());
  }
  }

  list<user> list=userservice.selectexcel(map); //查询数据
  
  xssfworkbook wb = new xssfworkbook(); // 声明一个工作薄
   xssfsheet sheet = wb.createsheet("用户信息"); // 生成一个表格
 
   integer columnindex = 0;
   sheet.setcolumnwidth(columnindex++, 3 * 512); // 设置表格第一列宽度为3个字节 
   sheet.setcolumnwidth(columnindex++, 10 * 512); //名称
   sheet.setcolumnwidth(columnindex++, 10 * 512); //年龄
   sheet.setcolumnwidth(columnindex++, 10 * 512); //备注
   
   // 生成一个样式 
   xssfcellstyle style1 = wb.createcellstyle(); 
   // 设置这些样式 
   style1.setfillforegroundcolor(indexedcolors.grey_25_percent.getindex());
   
   // 生成一个字体 
   xssffont font1 = wb.createfont(); 
   font1.setfontheightinpoints((short) 11); 
   font1.setfontname("黑体"); // 字体
   // 把字体应用到当前的样式 
   style1.setfont(font1); 
   
   //在sheet里增加合并单元格 
   cellrangeaddress cra = new cellrangeaddress(0, 0, 0, 7);  
   sheet.addmergedregion(cra);
   
   int rowint = 0; //列号
   xssfrow row = sheet.createrow(rowint++);
   
   xssfcell cell = row.createcell(0);
   cell.setcellstyle(style1);
   cell.setcellvalue("用户信息");
   
   int cellint = 0;
   row = sheet.createrow(rowint++);
   
   cell = row.createcell(cellint++);
   cell.setcellstyle(style1);
   cell.setcellvalue("序号");
   
   cell = row.createcell(cellint++);
   cell.setcellstyle(style1);
   cell.setcellvalue("名称");
   
   cell = row.createcell(cellint++);
   cell.setcellstyle(style1);
   cell.setcellvalue("年龄");
   
   cell = row.createcell(cellint++);
   cell.setcellstyle(style1);
   cell.setcellvalue("备注");
 
   int index = 0;
   if(list!=null && !list.isempty()){
    for(user obj:list){
    index++;
    cellint = 0;
     row = sheet.createrow(rowint++);
     
     cell = row.createcell(cellint++);
     cell.setcellvalue(index);
     
     cell = row.createcell(cellint++);
     cell.setcellvalue(obj.getname());
     
     cell = row.createcell(cellint++);
     cell.setcellvalue(obj.getage());
     
     cell = row.createcell(cellint++);
     cell.setcellvalue(obj.getremark());
    }
   }
   //反馈给前台状态
  response.getwriter().append("ok");
  //xssfworkbook对象保持到session里,供下载使用
  request.getsession().setattribute("xssfworkbook",wb);
 } catch (exception e) {
  e.printstacktrace();
 }
}

2、分离出来的下载方法

 /**
 * @param filename 下载文件名称
 * @param request 请求对象
 * @param response 响应对象
 * 2020-11-10 新增
*/
 @requestmapping("downloadexcel")
 public void downloadexcel(string filename,httpservletrequest request,httpservletresponse response) {
 if(str.isnotnull(filename)){
 user loginuser = (user) request.getsession().getattribute("loginuser");
 //检验下载路径并返回url
 string url = filetool.getdownloadurl(loginuser, filename, request);
 //从url里截取出文件全名
 filename = url.substring(url.lastindexof("/")+1);
 //创建文件输出流
 fileoutputstream fileout = null; 
 try {
  fileout = new fileoutputstream(url); 
  //获取保存在session中的待下载数据
  xssfworkbook wb = (xssfworkbook) request.getsession().getattribute("xssfworkbook");
  wb.write(fileout);
 } catch (filenotfoundexception e) {
  e.printstacktrace();
 }catch (ioexception e) {
  e.printstacktrace();
 }
 
 finally{ 
    if(fileout != null){ 
     try { 
      fileout.close(); 
     } catch (ioexception e) { 
      e.printstacktrace(); 
     } 
    } 
   } 
   
 try {
   system.out.println("------------开始下载文件---------------");
   file file = new file(url);
    // 以流的形式下载文件。
    inputstream fis = new bufferedinputstream(new fileinputstream(url));
    byte[] buffer = new byte[fis.available()];
    fis.read(buffer);
    fis.close();
    // 清空response
    response.reset();
    // 设置response的header
    response.addheader("content-disposition", "attachment;filename=" + new 
    string(filename.getbytes("utf-8"),
    "iso8859-1"));
    response.addheader("content-length", "" + file.length());
    outputstream toclient = new bufferedoutputstream(response.getoutputstream());
    response.setcontenttype("application/octet-stream");
    toclient.write(buffer);
    toclient.flush();
    toclient.close();
    //清除session里的数据
    request.getsession().removeattribute("xssfworkbook");
   } catch (ioexception ex) {
    ex.printstacktrace();
   }
 }
}

3、前台调用导出数据

 //导出请求
 function exportexcel(){
 var load = saveload("导出中,请稍后...",1); //打开一个等待框
 $.ajax({
   type: "post",
   url: "exportexcel",
   datatype:"text",
   error: function(request) {
    closesaveload(load,1);
    return false;
   },
   success: function(msg) {
    if(msg=='ok'){
    closesaveload(load,1); //关闭等待框
    //下载请求地址
    window.location.href="downloadexcel?filename=用户信息" rel="external nofollow" ;
    }else{
    closesaveload(load,1); //关闭等待框
    layer.msg("导出失败,刷新页面重试",{icon:2});
    return false;
    }
   }
  });
 }

效果如下:

java实现异步导出数据

总结:

以前是将封装数据和下载数据放一个方法里面,导致下载需要等待很久,而等待的时候,无法提示用户后台正在处理数据。将数据和下载分开后就可以达到等待时提示,加载完下载。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

相关标签: java 导出数据