SpringBoot+MyBatisPlus:分页查询、压缩文件导出大数据量解决方案

1、大数据量导出方案介绍

在SpringBoot中,可以使用MyBatis-Plus的流式查询功能实现大数据量的导出,并通过压缩文件的方式减小文件大小,提升导出效率。

具体实现步骤如下:

  1. 配置MyBatis-Plus的分页插件和流式查询插件。

  2. 创建一个Controller方法,接收客户端的请求,并使用流式查询功能查询出需要导出的数据。

  3. 将查询出的数据写入到Excel文件中,并使用Java原生的压缩类库将Excel文件压缩为zip文件。

  4. 将压缩后的文件作为响应内容,发送给客户端。

2、实际运用代码实践

下面是一个示例代码,演示了如何使用SpringBoot MyBatisPlus分页查询、压缩文件、导出大数据量的功能:

@GetMapping("/exportOrders")
public ResponseEntity<byte[]> exportOrders() throws IOException {
        // 定义信息
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        GZIPOutputStream gzipOut = new GZIPOutputStream(out);
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(gzipOut));
        String header = "id,address,launchName,orderNum,orderRemark";
        writer.write(header);
        writer.newLine();

        // 设置每页大小
        int pageNum = 1;
        int pageSize = 2000;
        boolean hasNextPage = true;
        // 分页查询需要导出的数据
        while (hasNextPage) {
            Page<RbgtOrder> page = new Page<>(pageNum, pageSize);
            IPage<RbgtOrder> orderPage = orderMapper.selectPage(page, null);
            List<RbgtOrder> orderList = orderPage.getRecords();
            System.out.println("当前页数-> pageNum:" + pageNum + ",总页数:pages:" + orderPage.getPages() + "");
            if (CollectionUtils.isNotEmpty(orderList)) {
                for (RbgtOrder order : orderList) {
                    String line = order.getId() + "," + order.getAddress() + "," + order.getLaunchName() + "," + order.getOrderNum() + "," + order.getOrderRemark();
                    writer.write(line);
                    writer.newLine();
                }
            }
            pageNum++;
            if (pageNum == orderPage.getPages()) {
                hasNextPage = false;
            }
        }
        writer.flush();
        writer.close();
        gzipOut.finish();
        byte[] bytes = out.toByteArray();

        // 生成对应压缩文件到制定目录(后续可以结合导出中间件,供客户端下载 -> 适用于大数据量导出,没问题)
        InputStream inputStream = new ByteArrayInputStream(bytes);
        MultipartFile file = new MockMultipartFile(ContentType.OCTET_STREAM.toString(), inputStream);
        file.transferTo(new File(getResourcesPath() + "orders.csv.gz"));

        // 请求页面输出压缩文件(适用于小数据量导出,没问题)
        HttpHeaders headers = new HttpHeaders();
        headers.setContentDispositionFormData("attachment", "orders.csv.gz");
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        return new ResponseEntity<>(bytes, headers, HttpStatus.OK);
    }

/**
     * 查询 - 实时获取resources实时新增的文件目录
     *
     * @param
     * @return java.lang.String
     * @Author 俞春旺
     * @Date 下午 07:29:28 2023年3月30日 0030
     **/
    public static String getResourcesPath() {
        // 这里需要注意的是ApplicationHome是属于SpringBoot的类
        // 获取项目下resources/static/img路径
        ApplicationHome applicationHome = new ApplicationHome(RbgtOrderController.class);

        // 保存目录位置根据项目需求可随意更改 - win和linux目录不一样
        String path = applicationHome.getDir().getParentFile().getParentFile().getAbsolutePath() + "/src/main/resources/temp/";
        System.out.println("path:" + path);
        return path;
    }

在这个示例代码中,我们使用了MyBatis-Plus的lambdaQuery方法进行了分页查询,同时使用了流式查询功能避免了内存占用过大的问题。在每次查询一定数量的数据后,我们将数据写入Excel文件并将Excel文件写入到临时文件中。最后,我们将临时文件压缩为zip文件并将其作为响应内容发送给客户端。

需要注意的是,这里使用了Java原生的压缩类库,并且每次只压缩一定数量的数据,以避免占用过多的内存和文件系统资源。如果需要导出的数据量非常大,建议考虑使用专门的压缩库或者将数据存储到分布式文件系统中。

其实说白了,就是时间换空间,后续可以结合消息中间件或者中间导出服务,将压缩文件上传到自己服务器,在通过客户端下载链接即可

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值