SpringBoot实现导出Excel功能
1 问题背景
需求要做一个导出excel的功能
2 前言
- 本篇着重阐述后端怎么实现,前端实现的部分只会粗略阐述。该实现方案是经过生产环境考验的,不是那些拿来练手的小demo。本文阐述的方案可以借鉴用来做毕设或者加到自己玩的项目中去。
- 再次声明,本文是百万级数据量的企业级解决方案,不是学校里面的毕设或者自己搭环境玩玩的小demo。客户不会去一页一页地点击导出,本文阐述的是一键导出几千行甚至上万行的数据。如果本文与你了解到的方案有出入可以在评论区交流,像那种导出几行或十来行的方案就不要说了。
- 有读者在评论里提问“请教百万行能撑住吗?”笔者没有去验证,有兴趣或者有疑问的读者可以去验证下,本文的解决方案是导出几千或上万行数据。本文也只是想介绍电商生产环境中真实的需求以及真实的解决方案,如果要导出百万行,那就只能采用异步方式去进行导出了,文末有提供思路。
3 实现思路
- 后端查询要导出的数据,此处简称data
- 使用阿里的EasyExcel组件将data写到HttpServletResponse里面,返回指定的响应头、响应内容的类型、字符编码。响应出去的数据是二进制数据,此处简称bytes数据
- 前端使用前端框架提供的方法,将 bytes数据转成blob,然后生成下载地址,然后进行下载
4 后端实现
要引入阿里的EasyExcel依赖,此处不赘述
<dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>2.1.7</version></dependency>
下面是excel文件要保存的信息,需要指定列头
@Data
public class UserInfoVO {@ExcelProperty(value = "用户ID",index = 0)private Long id;@ExcelProperty(value = "用户姓名",index = 1)private String username;@ExcelProperty(value = "性别",index = 2)private String sex;
}
导出的伪代码如下:
@PostMapping("/xx/xxx/xxx")public void export(HttpServletResponse reponse) {// 设置响应头等response.setHeader("Content-Disposition", "attachment;filename=" + "文件名(随便定义).xlsx");response.setContentType("application/vnd.ms-excel");response.setCharacterEncoding("UTF-8");// 查数据,假如要导出UserInfo的列表信息List<UserInfoVO> data = selectData();// 导出数据 EasyExcel.write(response.getOutputStream()).head(UserInfoVO.class).sheet().doWrite(data);}
5 设置Excel自适应列宽
思路:实现easyexcel提供的类并重写方法,写数据到HttpServletReponse的时候注册一个自适应列宽的bean
实现AbstractColumnWidthStyleStrategy类,如下所示:
public class CustomCellWriteWeightConfig extends AbstractColumnWidthStyleStrategy {private Map<Integer, Map<Integer, Integer>> CACHE = new HashMap<>();@Overrideprotected void setColumnWidth(WriteSheetHolder writeSheetHolder, List<CellData> cellDataList, Cell cell, Head head, Integer integer, Boolean isHead) {boolean needSetWidth = isHead || !CollectionUtils.isEmpty(cellDataList);if (needSetWidth) {Map<Integer, Integer> maxColumnWidthMap = CACHE.get(writeSheetHolder.getSheetNo());if (maxColumnWidthMap == null) {maxColumnWidthMap = new HashMap<>();CACHE.put(writeSheetHolder.getSheetNo(), maxColumnWidthMap);}Integer columnWidth = this.dataLength(cellDataList, cell, isHead);if (columnWidth >= 0) {if (columnWidth > 254) {columnWidth = 254;}Integer maxColumnWidth = maxColumnWidthMap.get(cell.getColumnIndex());if (maxColumnWidth == null || columnWidth > maxColumnWidth) {maxColumnWidthMap.put(cell.getColumnIndex(), columnWidth);Sheet sheet = writeSheetHolder.getSheet();sheet.setColumnWidth(cell.getColumnIndex(), columnWidth * 256);}}}}/*** 计算长度* @param cellDataList* @param cell* @param isHead* @return*/private Integer dataLength(List<CellData> cellDataList, Cell cell, Boolean isHead) {if (isHead) {return cell.getStringCellValue().getBytes().length;} else {CellData cellData = cellDataList.get(0);CellDataTypeEnum type = cellData.getType();if (type == null) {return -1;} else {switch (type) {case STRING:// 换行符(数据需要提前解析好)int index = cellData.getStringValue().indexOf("\n");return index != -1 ?cellData.getStringValue().substring(0, index).getBytes().length + 1 : cellData.getStringValue().getBytes().length + 1;case BOOLEAN:return cellData.getBooleanValue().toString().getBytes().length;case NUMBER:return cellData.getNumberValue().toString().getBytes().length;default:return -1;}}}}
}
注册自适应列宽的组件:
EasyExcel.write(response.getOutputStream()).head(SubscriptionOrderExportResp.class)// 注册自适应列宽组件.registerWriteHandler(new CustomCellWriteWeightConfig()).sheet().doWrite(data);
6 方案优缺点
优点:实现简单,轻量级。能快速迭代上线 。
缺点:使用了同步方式返回数据,如果excel文件的数据量很多,那么将耗费很多时间,甚至http连接已经断开了还未响应出去。
改进:本文解决方案是采用了同步方式导出,实时返回excel文件。可以做一个异步方式,后端创建一个任务异步生成excel文件,然后文件上传到对象存储服务器。前端轮询任务是否完成,后端返回文件地址给前端下载。
相关文章:
SpringBoot实现导出Excel功能
1 问题背景 需求要做一个导出excel的功能 2 前言 本篇着重阐述后端怎么实现,前端实现的部分只会粗略阐述。该实现方案是经过生产环境考验的,不是那些拿来练手的小demo。本文阐述的方案可以借鉴用来做毕设或者加到自己玩的项目中去。再次声明,…...
NSSCTF之Misc篇刷题记录⑧
NSSCTF之Misc篇刷题记录 [MMACTF 2015]welcome[广东强网杯 2021 团队组]欢迎参加强网杯[虎符CTF 2022]Plain Text[SWPUCTF 2021 新生赛]原来你也玩原神[SWPUCTF 2021 新生赛]我flag呢?[鹤城杯 2021]New MISC NSSCTF平台:https://www.nssctf.cn/ PS&…...
从零开始学习Linux运维,成为IT领域翘楚(七)
文章目录 🔥Linux下常用软件安装_JDK和Tomcat安装🔥Linux下常用软件安装_MySQL安装🔥Linux下常用软件安装_MySQL卸载 🔥Linux下常用软件安装_JDK和Tomcat安装 Jdk 安装 解压jdk安装包 tar -zxvf jdk-8u201-linux-x64.tar.gz -C/…...
优漫动游设计APP的UI界面需要注意哪些问题?
一、加载 加载时间的长短,很大程度的决定了用户体验是否有所提升,虽然理想中的页面加载出来应该一秒就够了,但是设计师不要忽略网络问题!如果网速不够的话,页面加载三五秒都算是快的了,所以在用户等待的过程中&a…...
面试 004
什么是 Java 内存结构 Java 内存结构就是 JVM 的运行书数据区的内存结构: 里面有堆、虚拟机栈、本地方法栈、程序计数器; 虚拟机栈:里面的数据结构是栈帧,存放了方法名,局部变量等信息 方法区在 1.8 的时候…...
CCF-202206-2-寻宝!大冒险!
目录 题目背景 问题描述 一、思路: 二、实现方法(C) 2.1、方法一(int储存) 思路: C实现如下: 2.2、方法二(结构体储存) 思路: 注意:边界…...
二叉搜索树中的众数
1题目 给你一个含重复值的二叉搜索树(BST)的根节点 root ,找出并返回 BST 中的所有 众数(即,出现频率最高的元素)。 如果树中有不止一个众数,可以按 任意顺序 返回。 假定 BST 满足如下定义&…...
认识JSP
什么是JSP? JSP(Java Server Pages)是一种类似于HTML的标记语言,用于创建动态Web页面。与HTML不同的是,JSP页面中可以嵌入Java代码,由Web服务器在动态页面中生成HTML代码,从而实现Web应用程序的前端交互效…...
MySQL数据管理
一、MySQL数据库管理 1、库和表 行(记录):用来描述一个对象的信息 列(字段):用来描述对象的一个属性 2、常用的数据类型 int :整型 float :单精度浮点 4字节32位 double &…...
第十九章 Unity 其他 API
本节介绍一些其他经常使用的Unity类。首先,我们回顾一下Vector3向量类,它既可以表示方向,也可以表示大小。它在游戏中可以用来表示角色的位置,物体的移动/旋转,设置两个游戏对象之间的距离。在我们之前的课程中&#x…...
sha256算法详解,用C语言模拟sha256算法
SHA-256是一种加密算法,它可以将任意长度的数据块计算出一个固定长度的输出值,通常是256位。SHA-256具有以下特点: 1. 固定输出长度:SHA-256的输出长度为256位,不受输入数据的长度限制。 2. 不可逆性:SHA-256采用单向哈希函数,即无法从输出值反向推出输入数据。 3. 抗…...
前端技术未来发展展望
前端技术在未来的发展中将继续保持快速、变化多样和创新性强的趋势。以下是我认为前端技术未来发展的几个方向: 框架和库的演进:框架和库的更新换代将继续加速。React、Vue、Angular等主流框架的更新周期将会缩短,同时各自的生态系统也将更加…...
第四十六天|dp
今天的题还是完全背包的题 139. Word Break 这道题其实用deque也能做,但是需要cache去记录之前尝试过的值,.相对简单的办法就是用完全背包了 这道题worddict就是物品.我们的dp[i]代表到i为止是不是能满足题意分成segmentation 处置化全为false,但是dp[0]True.这是因为为0时…...
汇编语言-复习自用
本文用于自我复习汇编语言,参考b站一位老师的讲解整理而成,感谢老师的无私付出视频链接链接 文章目录 1.第一章1.1计算机组成1.2读取1.3 寄存器及数据存储1.4 mov和and指令1.5 确定物理地址1.6 内存分段表示法1.7debug使用1.8CS:IP1.9jmp指令改变csip1.1…...
Android moneky自动点击应用设想
近期又有人发错私密消息到群聊天里,造成巨大反应的事件,可谓是一失手成大恨,名利受损。 而如果手机里安装一个monkey自动点击程序,没事的时候,跑跑monkey,倒一杯茶,静静的看手机屏幕在那里点击&…...
16.基于主从博弈理论的共享储能与综合能源微网优化运行研究
说明书 MATLAB代码:基于主从博弈理论的共享储能与综合能源微网优化运行研究 关键词:主从博弈 共享储能 综合能源微网 优化调度 参考文档:《基于主从博弈理论的共享储能与综合能源微网优化运行研究》完全复现 仿真平台:MATLAB …...
使用 ESP32 设计智能手表第 2 部分 - 环境光和心率传感器
我们研究了如何为我们的智能手表项目制作一些有趣的表盘。在这一部分中,我们将研究如何将一些传感器连接到我们的智能手表,并将连接 BH1750 环境光传感器和 MAX30102 心率传感器。我们将分别研究这些模块中的每一个的接口。 先决条件——安装必要的库 本文下方提供的 GitHub …...
分布式事务 --- 理论基础、Seata架构、部署
一、分布式事务问题 1.1、本地事务 本地事务,也就是传统的单机事务。在传统数据库事务中,必须要满足四个原则: 1.2、分布式事务 分布式事务,就是指不是在单个服务或单个数据库架构下,产生的事务,例如&am…...
低代码开发重要工具:JVS列表页字段样式配置说明
列表页中,通常存在各种各样的样式控制,例如字段宽度需要可调、字段的颜色根据内容变化等,那么我们接下来介绍下字段的样式控制的内容以及对应的效果。 1、字段样式控制配置位置 进入列表页的 数据配置界面,每个字段可以有独立的配…...
explain结果字段分析
select_type simple:表示不需要union操作或者不包含子查询的简单select语句。有连接查询时,外层的查询为simple且只有一个。 primary:一个需要union操作或者含有子查询的select,位于最外层的单位查询的select_type即为primary且只…...
MySQL连接查询
MySQL连接查询 在多表联合查询时,为了减少查询的次数,使用连接查询可以一次查询多个相关联表的数据。 MySQL连接查询:分为内连接查询和外连接查询。 其中外连接查询又分成 left连接查询 和 right连接查询。 下午为两张数据库表,表…...
7. Docker——Dockerfile
本章讲解知识点 DockerfileDockerfile 常用命令Dockerfile 综合示例Docker Compose当我们理解了镜像的基本原理后,我们就可以开始 Dockerfile 的学习了。 1. Dockerfile Dockerfile 是用于构建 Docker 镜像的脚本。它包含一组指令,按顺序执行以创建 Docker 镜像,从而使其可…...
Input事件在应用中的传递(一)
Input事件在应用中的传递(一) hongxi.zhu 2023-4-25 前面我们已经梳理了input事件在native层的传递,这一篇我们接着探索input事件在应用中的传递与处理,我们将按键事件和触摸事件分开梳理,这一篇就只涉及按键事件。 一、事件的接收 从前面的…...
我在VScode学Java(Java一维数组)
我的个人博客主页:如果\真能转义1️⃣说1️⃣的博客主页 关于Java基本语法学习---->可以参考我的这篇博客:(我在Vscode学Java) 我在VScode学Java(Java一维数组) Java 一维数组 声明数组:先声明,后使用 动态分配内…...
不能使用chatGPT?这3个平替甚至比chatGPT更强
不能使用chatGPT?这3个平替甚至比chatGPT更强 chatGPT,一款由OpenAI开发的新型AI聊天机器人,正在势如破竹地改变着许多人的工作和生活方式。作为一款基于大语言模型的聊天机器人,chatGPT能够理解自然语言并进行人机对话。与传统的…...
基于SLM调制器,MIT研发高效率全息显示方案
此前,青亭网曾报道过NVIDIA、三星、剑桥大学等对空间光调制器(SLM)全息方案的探索。空间光调制器可调节光波的空间分布,在电驱动信号控制下,可改变光在空间中传播的振幅、强度、相位、偏振态等特性,从而形成…...
【Docker】镜像与docker数据卷
文章目录 一、镜像1、镜像2、镜像原理之联合文件系统3、镜像原理之分层4、commit镜像 二、数据卷1、数据卷2、-v使用数据卷3、实战:MySQL 同步数据4、docker volume相关指令5、匿名和具名挂载6、数据卷之Dockerfile7、数据卷容器 一、镜像 1、镜像 镜像是一种轻量级…...
机器学习小结之KNN算法
文章目录 前言一、概念1.1 机器学习基本概念1.2 k 值1.3 距离度量1.4 加权方式 二、实现2.1 手写实现2.2 调库 Scikit-learn2.3 测试自己的数据 三、总结3.1 分析3.2 KNN 优缺点 参考 前言 KNN (K-Nearest Neighbor)算法是一种最简单,也是一个很实用的机器学习的…...
函函函函函函函函函函函数——two
🤩本文作者:大家好,我是paperjie,感谢你阅读本文,欢迎一建三连哦。 🥰内容专栏:这里是《C知识系统分享》专栏,笔者用重金(时间和精力)打造,基础知识一网打尽,…...
SpringCloud学习笔记06
九十五、Cloud Alibaba简介 0、why会出现SpringCloud alibaba Spring Cloud Netflix项目进入维护模式 1、是什么 官网:spring-cloud-alibaba/README-zh.md at 2.2.x alibaba/spring-cloud-alibaba GitHub 2、能干嘛 3、去哪下 spring-cloud-alibaba/README-…...
建立网站tk/网络热词英语
在APPchart 中新建一个文件夹,和两个文件,结构如下: templatetags/__init__.pymytags.pymytags.py文件中自定义函数 from django import templateregister template.Library()register.filter def startswith(value, start):""&…...
中山建设安监站网站/网站百度收录
各位朋友,大家早上好!我是张小龙。 非常感谢大家一大早来到广州参加微信公开课。去年公开课是我第一次露面,并且在去年差不多这个时候时候宣布了我们的小程序要启动并且准备投入到公众号之外新的一种服务的形态里面去。 今年,我的…...
wordpress博客添加到菜单/小红书新媒体营销案例分析
本题比较困难的地方对于我来说应该是输入,后来参考了别人的代码原来还有stringstream这么好用的东西 还有就是方向的处理上面,lrj的方法比较巧妙,他是把方向全部转化成0-3然后一一对应数组中的元素 #include<iostream>//不需要判断边…...
jsp网站开发书籍推荐/百度一下百度一下你知道
近期小麦我经常收到很多用户的反馈,想知道Smartbi的报表能不能从微信/钉钉之类的直接跳转到已做好的报表页面?他们都希望通过这种方式尽可能地避免由于各个管理软件账号密码不同而造成的不便,能够在日常工作上更快地展开智能数据可视化分析。 这里小麦…...
wordpress 多产品主图/连云港百度推广总代理
使用 MySQL自带命令 mysqldumpslow 查看 OPTIONS -s ORDER ORDER, 主要有 c, t, l, r 和 ac, at, al, ar, 分别是按照 query次数, 时间, lock的时间和返回的记录数来排序, 前面加了a时倒序.-t NUM top NUM, 即为返回前面多少条的数据.-g PATTERN grep: 后边可以写一个正则匹配模…...
网站各页面/如何推广app赚钱
鉴于河南是oi弱省,所以想来这道题也没什么人会翻出来写吧,而且这还是haoi2009的一道简单题目,所以估计也没几个人会写博客的,那么看在我这么弱的份上,我觉得是应该写一篇出来的。 这道题我是按照贪心写的(毕…...