Excel Export 踩坑注意点+导出方案设计

产品需求

产品经理需要导出一个页面的所有的信息到 EXCEL 文件。

需求分析

对于 excel 导出,是一个很常见的需求。

最常见的解决方案就是使用 poi 直接同步导出一个 excel 文件。

客户体验 & 服务性能

  • 客户体验

如果导出的文件比较大,比如几十万条数据,同步导出页面就会卡主,用户无法进行其他操作。

  • 服务性能

导出的时候,任务比较耗时就会阻塞主线程。

如果导出的服务是暴露给外部(前后端分离),这种大量的数据传输十分消耗性能。

解决方案

使用异常处理导出请求,后台 MQ 通知自己进行处理。

MQ 消费之后,多线程处理 excel 文件导出,生成文件后上传到 FTP 等文件服务器。

前端直接查询并且展现对应的任务执行列表,去 FTP 等文件服务器下载文件即可。

EXCEL 导出需要考虑的问题

OOM

正常的 poi 在处理比较大的 excel 的时候,会出现内存溢出。

网上的解决方案也比较多。

比如官方的 SXSSF (Since POI 3.8 beta3) 解决方式。

当然,这种写法比较麻烦。

可以选择一些封装好的 excel 工具,解决 oom 问题:

iexcel excel 更加优雅地读取和写入,解决 excel OOM 问题

FULL GC

如果一次查询 100W 条数据库,然后把这些信息全部加载到内存中,是不可取的。

建议有2个:

  1. 限制每一次分页的数量。比如一次最多查询 1w 条。分成 100 次查询。(必须)

  2. 限制查询得总条数。比如限制为最多 10W 条。(根据实际情况选择)

虽然使用者提出要导出类似于 3 个月的所有信息,但是数量太多,毫无意义。(提出者自己可能体会不到)

尽量避免 FULL-GC 的情况发生,因为目前的所有方式对于 excel 的输出流都会占用内存,100W 条很容易导致 FULL-GC。

数据库的压力

去数据库读取的时候一定要记得分页,免得给数据库太大的压力。

一次读取太多,也会导致内存直线上升。

比如 100W 条数据,则分成 100 次去数据库读取。

网络传输

传统的 excel 导出,都是前端一个请求,直接 HTTP 同步返回。导出 100W 条,就在那里傻等。

这客户体验不友好,而且网络传输,系统占用多种问题。

建议使用异步处理的方式,将文件上传到文件服务器。前端直接去文件服务器读取。

编程的便利性

对于上面提到的工具,比如 Hutool,在表头的处理方面没法很方便的统一。

你可以自己定义类似于 easypoi/easyexcel 中的注解,自己反射解析。

然后统一处理表头即可。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,这里是SpringBoot+Mybatis-plus整合easyExcel批量导入Excel到数据库+导出Excel的方法。 1. 添加依赖 在 pom.xml 文件中添加以下依赖: ```xml <!-- easyExcel --> <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>2.1.6</version> </dependency> <!-- mybatis-plus --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.2</version> </dependency> ``` 2. 创建实体类 创建一个实体类,用于映射 Excel 表格中的数据。 ```java @Data public class User { @ExcelProperty("姓名") private String name; @ExcelProperty("年龄") private Integer age; @ExcelProperty("性别") private String gender; } ``` 3. 创建Excel读取器 创建一个 Excel 读取器,用于读取 Excel 表格中的数据,并将数据存储到数据库中。 ```java @Component public class ExcelReader { @Autowired private UserService userService; /** * 读取 Excel 表格中的数据,并将数据存储到数据库中 */ public void readExcel(String fileName) { EasyExcel.read(fileName, User.class, new UserExcelListener()).sheet().doRead(); } /** * 用户Excel监听器 */ private class UserExcelListener extends AnalysisEventListener<User> { /** * 每读取一行数据,就会调用该方法 */ @Override public void invoke(User user, AnalysisContext context) { userService.save(user); } /** * 读取完整个 Excel 表格后,会调用该方法 */ @Override public void doAfterAllAnalysed(AnalysisContext context) { // do nothing } } } ``` 4. 创建Excel导出器 创建一个 Excel 导出器,用于从数据库中获取数据,并将数据导出Excel 表格中。 ```java @Component public class ExcelWriter { @Autowired private UserService userService; /** * 将用户数据导出Excel 表格中 */ public void writeExcel(String fileName) { List<User> userList = userService.list(); EasyExcel.write(fileName, User.class).sheet().doWrite(userList); } } ``` 5. 创建Controller 创建一个 Controller,用于接收前端请求,并调用相应的方法处理请求。 ```java @RestController @RequestMapping("/user") public class UserController { @Autowired private ExcelReader excelReader; @Autowired private ExcelWriter excelWriter; /** * 批量导入用户数据 */ @PostMapping("/import") public void importExcel(@RequestParam("file") MultipartFile file) throws IOException { excelReader.readExcel(file.getInputStream()); } /** * 导出用户数据到Excel */ @GetMapping("/export") public void exportExcel(HttpServletResponse response) throws IOException { String fileName = "用户信息.xlsx"; response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8")); response.setContentType("application/vnd.ms-excel"); excelWriter.writeExcel(response.getOutputStream()); } } ``` 6. 配置文件 在 application.yml 文件中添加数据库连接信息。 ```yaml spring: datasource: driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai username: root password: root mybatis-plus: mapper-locations: classpath:/mapper/*.xml type-aliases-package: com.example.demo.domain ``` 7. 测试 启动应用程序,并在浏览器中访问以下地址: - http://localhost:8080/user/export导出 Excel 表格 - http://localhost:8080/user/import :导入 Excel 表格 以上就是 SpringBoot+Mybatis-plus整合easyExcel批量导入Excel到数据库+导出Excel 的方法了,希望能帮到你。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值