热门标签 | HotTags
当前位置:  开发笔记 > 前端 > 正文

java实现异步导出数据

这篇文章主要为大家详细介绍了java实现异步导出数据,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

问题概述:

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

解决办法:

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

demo:

1、获取并封装数据

@RequestMapping("exportExcel") //用户数据导出
 public void exportExcel(HttpServletRequest request, HttpServletResponse response) {
 Map map = new HashMap();
 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 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;
    }
   }
  });
 }

效果如下:

总结:

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

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


推荐阅读
  • 本文介绍了 PHP 的基本概念、服务器与客户端的工作原理,以及 PHP 如何与数据库交互。同时,还涵盖了常见的数据库操作和安全性问题。 ... [详细]
  • 本文详细解析了如何使用Python的urllib模块发起POST请求,并通过实例展示如何爬取百度翻译的翻译结果。 ... [详细]
  • 本文详细介绍了如何使用 HTML 和 CSS 对文件上传按钮进行样式美化,使用户界面更加友好和美观。 ... [详细]
  • 当unique验证运到图片上传时
    2019独角兽企业重金招聘Python工程师标准model:public$imageFile;publicfunctionrules(){return[[[na ... [详细]
  • 理解文档对象模型(DOM)
    本文介绍了文档对象模型(DOM)的基本概念,包括其作为HTML文档的节点树结构,以及如何通过JavaScript操作DOM来实现网页的动态交互。 ... [详细]
  • 本文探讨了浏览器的同源策略限制及其对 AJAX 请求的影响,并详细介绍了如何在 Spring Boot 应用中优雅地处理跨域请求,特别是当请求包含自定义 Headers 时的解决方案。 ... [详细]
  • ServletContext接口在Java Web开发中扮演着重要角色,它提供了一种方式来获取关于整个Web应用程序的信息。通过ServletContext,开发者可以访问初始化参数、共享数据以及应用资源。 ... [详细]
  • AJAX技术允许网页在不重新加载整个页面的情况下进行异步更新,通过向服务器发送请求并接收JSON格式的数据,实现局部内容的动态刷新。 ... [详细]
  • C# 对象转 JSON 字符串的方法与应用
    本文介绍如何在 C# 中使用一般处理程序(ASHX)将对象转换为 JSON 字符串,并通过设置响应类型为 application/json 来确保客户端能够正确解析返回的数据。同时,文章还提供了 HTML 页面中不依赖 jQuery 的 AJAX 方法来接收和处理这些 JSON 数据的具体实现。 ... [详细]
  • 如何在Windows 10的Bash中排除系统PATH
    探讨了在Windows 10的Bash环境中,如何通过调整注册表设置来避免调用Win32程序,确保使用的是Bash环境下的工具版本。 ... [详细]
  • 2023年1月28日网络安全热点
    涵盖最新的网络安全动态,包括OpenSSH和WordPress的安全更新、VirtualBox提权漏洞、以及谷歌推出的新证书验证机制等内容。 ... [详细]
  • 汇总了2023年7月7日最新的网络安全新闻和技术更新,包括最新的漏洞披露、工具发布及安全事件。 ... [详细]
  • SSE图像算法优化系列三:超高速导向滤波实现过程纪要(欢迎挑战)
    自从何凯明提出导向滤波后,因为其算法的简单性和有效性,该算法得到了广泛的应用,以至于新版的matlab都将其作为标准自带的函数之一了&#x ... [详细]
  • 深入解析JVM内存模型与分配机制
    本文详细探讨了JVM内存结构的主要组成部分,包括Java虚拟机栈、Java堆、方法区等,并深入分析了HotSpot虚拟机的分代收集策略及其对不同内存区域的管理方式。 ... [详细]
  • 本文将详细介绍如何在ThinkPHP6框架中实现多数据库的部署,包括读写分离的策略,以及如何通过负载均衡和MySQL同步技术优化数据库性能。 ... [详细]
author-avatar
喜欢香覀香的树花园
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有