【EasyExcel】封装一个分页写数据的通用方法(保姆级),继上一篇easyExcel导出上线后的优化

这篇具有很好参考价值的文章主要介绍了【EasyExcel】封装一个分页写数据的通用方法(保姆级),继上一篇easyExcel导出上线后的优化。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

【EasyExcel】封装一个分页写数据的通用方法

需求:通过elasticsearch查询出来一次性写,在大数据量时存在OOM的隐患分页查询、分批次写数据,避免导出大数据量时内存消耗陡增基于elasticsearch分页查询;mybatis-puls同理


前言

在上个博客中解决了线上导出字体依赖的问题,由于涉及的导出模块较多,因为打算封装一个方法做通用导出。

一、所需依赖

1、easyexcel mavn 依赖文件

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>2.1.1</version>
            <optional>true</optional>
        </dependency>

二、源码实现

1、依赖的枚举类:ExcelPageEnum(自定义)

ExcelPageEnum:

/**
 * @className: ExcelPageEnum
 * @description: 存储 XLS与XLSX每次最大写入与sheet最大Row的枚举
 * @author: 云野
 * @date: 2022/8/12
 */
public enum ExcelPageEnum {
  /**
   * 
   * default export xlsx, page size 10000, sheet max row 1000000
   * @author: 云野
   * @date: 2022/8/12
   */
  XLS(10_000, 60_000),
  XLSX(10_000, 1_000_000);

  private int pageSize;
  private int sheetMaxRow;

  ExcelPageEnum(int pageSize, int sheetMaxRow) {
    this.pageSize = pageSize;
    this.sheetMaxRow = sheetMaxRow;
  }

  public int getPageSize() {
    return pageSize;
  }

  public int getSheetMaxRow() {
    return sheetMaxRow;
  }
}

2、依赖的核心接口类:PageQueryService(自定义)

/**
 * @className: PageQueryService
 * @description: 实现通用的核心接口
 * @author: 云野
 * @date: 2022/8/12
 */
@FunctionalInterface
public interface PageQueryService<E> {

  /**
   * 带条件分页查询所有数据
   *
   * @return Result<List>
   */
  List<E> findByPage(Integer current, Integer size);
}

3、最终调用工具类: EasyExcelUtils

/**
 * 通用导出方法
 *
 * @className: EasyExcelUtils
 * @author: 云野
 * @date: 2022/8/12
 */
@Slf4j
@Component
public class EasyExcelUtils extends EasyExcel {

  public static void pageWrite(
      ExcelWriter excelWriter,
      String sheetName,
      Integer totalCount,
      HttpServletResponse response,
      PageQueryService pageQueryService) {

    // default export xlsx, page size 10000, sheet max row 1000000
    int pageSize = ExcelPageEnum.XLSX.getPageSize();
    int sheetMaxRow = ExcelPageEnum.XLSX.getSheetMaxRow();

    ExcelTypeEnum excelType = excelWriter.writeContext().writeWorkbookHolder().getExcelType();
    boolean isXls = excelType != null && ExcelTypeEnum.XLS.getValue().equals(excelType.getValue());
    if (isXls) {
      pageSize = ExcelPageEnum.XLS.getPageSize();
      sheetMaxRow = ExcelPageEnum.XLS.getSheetMaxRow();
    }

    try {
      // 下方使用了用户自己选择文件保存路径的方式,所以需要配请求参数,如果使用固定路径可忽略此代码
      String filename = URLEncoder.encode(sheetName + ".xlsx", "UTF-8");
      response.setCharacterEncoding("UTF-8");
      // 设定输出文件头
      response.setHeader("Content-disposition", "attachment; filename=" + filename);
      // 定义输出类型
      response.setContentType("application/x-xls");

      // 这里其实就是把上面的方法分开写,写入同一个sheet
      WriteSheet writeSheet = EasyExcelFactory.writerSheet(sheetName).build();

      // compute page count, sheet count
      long pageCount = (totalCount - 1) / pageSize + 1;
      long sheetCount = (totalCount - 1) / sheetMaxRow + 1;
      int currentPage = 0;

      // page write data
      WriteSheet sheet = null;
      for (int i = 0; i < sheetCount; i++) {
        Pageable pageable = new PageRequest(i, pageSize);
        sheet = EasyExcelFactory.writerSheet(i, sheetName + i).build();
        for (int j = 0; j < (sheetMaxRow / pageSize); j++) {
          excelWriter.write(pageQueryService.findByPage(currentPage, pageSize), sheet);
          currentPage++;
          if (currentPage >= pageCount) {
            break;
          }
        }
      }
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      if (excelWriter != null) {
        excelWriter.finish();
      }
    }
  }
}

三、代码调用方式

1、Controller层代码

@Slf4j
@Api(tags = "后台--货源服务API")
@RestController
@RequestMapping("/api/admin")
public class AdminCargoOwnerSupplyResource {

  @Autowired private HttpServletResponse response;
  @Autowired private CargoOwnerSupplyService cargoOwnerSupplyService;
  
  /**
   * @author: 云野 @Description: 导出货源Excel
   * @date: 2022/8/12
   * @param: [queryRequest]查询条件对象
   */
  @ApiOperation(value = "导出货源", httpMethod = "GET")
  @GetMapping(value = "/url")
  public void exportExcel(AdminCargoOwnerSupplyQueryRequest queryRequest) {

    ServletOutputStream outputStream = null;
    try {
      outputStream = response.getOutputStream();
    } catch (IOException e) {

    }
    // build excel writer , CargoOwnerSupplyExportExcel 为自定义的导出类
    // excelType:导出类型,我这边导出的是XLSX文件
    ExcelWriter excelWriter =
        EasyExcelFactory.write(outputStream, CargoOwnerSupplyExportExcel.class)
            .excelType(ExcelTypeEnum.XLSX)
            .build();
            
    // page write  ; “CargoOwnerSupply”为写出的文件名字
    // cargoOwnerSupplyService.countOfQueryRequest(queryRequest) 是调用的方法,查询需要导出多少数据
    EasyExcelUtils.pageWrite(
        excelWriter,
        "CargoOwnerSupply",
        cargoOwnerSupplyService.countOfQueryRequest(queryRequest),
        response,
        (currentPage, pageSize) ->
            cargoOwnerSupplyService.exportExcel(
                queryRequest, new PageRequest(currentPage, pageSize)));
  }
}

2、ExportExcel导出层实体(自定义,也可以是直接的entity实体)

/**
 * @Author 云野 @Description: 导出Excel后台货源 @Date 2022/8/12
 */
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class CargoOwnerSupplyExportExcel {
  /** 账号 */
  @ExcelProperty(value = "账号", index = 0)
  private String account;

  /** 联系人 */
  @ExcelProperty(value = "联系人", index = 1)
  private String contactPerson;

  /** 发布时间 */
  @ExcelProperty(value = "发布时间", index = 2)
  private String createTime;

  /** 货物名称 */
  @ExcelProperty(value = "货物名称", index = 4)
  private String goodsName;

  /** 发货量 */
  @ExcelProperty(value = "发货量", index = 5)
  private Integer deliveryMount;

}

3、Service接口层

/** @Author 云野 @Description: @Date 2022/8/12 */
public interface CargoOwnerSupplyService {

  /** 根据条件查询货源数量 */
  Integer countOfQueryRequest(AdminCargoOwnerSupplyQueryRequest request);

  /**
   * 导出Excel
   *
   * @param request
   * @param pageable
   */
  List<CargoOwnerSupplyExportExcel> exportExcel(
      AdminCargoOwnerSupplyQueryRequest request, Pageable pageable);

}

4、Service接口实现层

/** @Author 云野 @Description: @Date 2022/8/12 */
public interface CargoOwnerSupplyServiceImpl {

  /** 根据条件查询货源数量 */
    @Override
  public Integer countOfQueryRequest(AdminCargoOwnerSupplyQueryRequest request) {
    // 这是是我Elasticsearch的查询数量的方法,如果是sql的话,用自己的api
    return Integer.valueOf(
        String.valueOf(
            elasticsearchTemplate.count(
                new NativeSearchQueryBuilder().withQuery(queryConditions(request)).build(),
                CargoOwnerSupplyDTO.class)));
  }

  /**
   * 
   * 因为我没有直接使用数据库查询出来的entity实体对象,而是再封装定义了一层ExportExcel实体对象,因此我这边需要准备这个赋值的方式,如果看官们直接用的数据库查询出来的 entity实体,那么就不需要赋值的过程
   * @author: 云野 
   * @Description: 导出Excel
   * @date: 2022/8/12
   * @param: [request(查询条件), pageable(分页查询)]
   * @return: void
   */
  @Override
  public List<CargoOwnerSupplyExportExcel> exportExcel(
      AdminCargoOwnerSupplyQueryRequest request, Pageable pageable) {

    // 通过条件从数据库查询所有,返回一个List
    List<CargoOwnerSupplyVo> cargoOwnerSupplyList =
        cargoOwnerSupplyWebMapper.dtos2vos(adminFindAll(request, pageable).getContent());

    // 初始化List
    ArrayList<CargoOwnerSupplyExportExcel> list = new ArrayList<>();
    // 遍历查询出来的 List<CargoOwnerSupplyVo> , 然后进行赋值到 ArrayList<CargoOwnerSupplyExportExcel>的操作
    cargoOwnerSupplyList.stream()
        .forEach(
            vo -> {
              // 基于@Builder注解进行赋值
              CargoOwnerSupplyExportExcel excel = CargoOwnerSupplyExportExcel
              .builder()
              .account(vo.getContactPhone())
              .contactPerson(vo.getContactPerson())
              .createTime(vo.getCreateTime())
              .goodsName(vo.getGoodsName())
              .deliveryMount(vo.getDeliveryMount()).build();
     
              list.add(excel);
            });
    return list;
  }

}

三、总结

看过我以前博客的小伙伴应该知道,我这边所有的案例都是开发时碰到的,同时我这边的Data层用的是Elasticsearch+Spring Data Jpa ,因为公司用的就是这个呀,所以案例中出现 的查询方案案例,如果使用Sql的小伙伴不需要进行深究,只需要明白一点就行,这种时候可以直接使用Sql中同样的查询即可。
看到这里如果帮助到了你,给个点赞,谢谢啦!文章来源地址https://www.toymoban.com/news/detail-470113.html

到了这里,关于【EasyExcel】封装一个分页写数据的通用方法(保姆级),继上一篇easyExcel导出上线后的优化的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 鸿蒙API9+axios封装一个通用工具类

    使用方式: 打开Harmony第三方工具仓,找到axios,如图: 第三方工具仓网址:https://ohpm.openharmony.cn/#/cn/home 在你的项目执行命令:ohpm install @ohos/axios 前提是你已经装好了ohpm ,如果没有安装,可以在官网找到详细的安装教程; 注意:不是在你的entry目录下,比如你的项目名称:

    2024年04月17日
    浏览(48)
  • 【EasyExcel】在SpringBoot+VUE项目中引入EasyExcel实现对数据的导出(封装工具类)

    一、引入EasyExcel 通过maven引入,坐标如下: 二、后端代码演示 下面以权限系统中的角色列表为案例,演示如何导出数据 实体类 工具类 通过@Component把工具类交给spring管理,在需要使用的地方使用@Resource注入即可 将泛型设置为 \\\" ? \\\",来表示任意类型,可以通过这一个方法完成

    2024年02月16日
    浏览(42)
  • 万级数据优化EasyExcel+mybatis流式查询导出封装

    时间 更新内容 2023/09/23 fix: 每个sheet大小和存储内存条数一致的bug update: 增大一个sheet的默认容量 我们不妨先给大家讲一个概念,利用此概念我们正好给大家介绍一个数据库优化的小技巧: 需求如下:将一个地市表的数据导出70万条。 如果你不假思索,直接一条sql语句搞上去

    2024年02月11日
    浏览(47)
  • Java多线程查表(封装方法 多表通用)

    经过多线程的学习和实践 总结了两种多线程查表方法  两种方法都经过我的封装 某表使用时 server层加上方法sql即可 查询流程: 1 count全表条数 2 通过总条数 将全表数据分为10份 3 开辟10个线程查询limit语句(线程数可自定义) 以下方法均以mysql数据库测试 其他库同理 目录 一 线

    2024年02月12日
    浏览(32)
  • 从vue小白到高手,从一个内容管理网站开始实战开发第七天,登录功能后台功能设计--通用分页、枚举以及相关工具类

    上一篇实现了数据库访问层的相关功能,还没有了解的小伙伴可以去看前面文章实现的内容,因为每一篇内容都是连贯的,不学习的话可能下面的内容学习起来会有点摸不着头脑 从vue小白到高手,从一个内容管理网站开始实战开发第六天,登录功能后台功能设计--API项目中的

    2024年01月22日
    浏览(30)
  • 封装数据访问通用类DbHelper

            数据交互:增上改查                相同的事情:连接                T-SQL命令,Command                执行命令,选择执行方式         得到相应结果         关闭连接 将一些从重复的逻辑进行封装,达到通用的目的 提高复用率,提高效果,不在考

    2024年02月02日
    浏览(28)
  • 自己动手封装axios通用方法并上传至私有npm仓库:详细步骤与实现指南

    一、构建方法 确定工具库的需求和功能:在开始构建工具库之前,你需要明确你的工具库需要包含哪些方法及工具,以及这些工具或方法应该具备哪些功能。这有助于你更好地规划你的开发工作。 编写工具代码:使用你熟悉的前端框架(如React、Vue等)编写工具代码。确保你

    2024年04月14日
    浏览(37)
  • 使用EasyExcel实现通用导出功能

    JDK 1.8+ EasyExcel 2.2.7 此功能可以实现根据传入自定义的 导出实体类或Map 进行excel文件导出。若根据Map导出,导出列的顺序可以自定义。 话不多说,直接看代码 点击查看代码 点击查看代码 点击查看代码 点击查看代码 点击查看代码 点击查看代码 点击查看代码

    2024年02月05日
    浏览(19)
  • 一个通用的EXCEL生成下载方法

    Excel是一个Java开发中必须会用到的东西,之前博主也发过一篇关于使用Excel的文章,但是最近工作中,发现了一个更好的使用方法,所以,就对之前的博客进行总结,然后就有了这篇新的,万能通用的方法说明书了 好了,闲话不多说,直接上干货了 控制器代码如下 上面总结

    2024年02月10日
    浏览(28)
  • 一个通用的es聚合查询方法

    调整方法如下: getSearchCondition为数据库中配置的条件: {\\\"query\\\":{\\\"bool\\\":{\\\"must\\\":[{\\\"exists\\\":{\\\"field\\\":\\\"db_type\\\",\\\"boost\\\":1}},{\\\"exists\\\":{\\\"field\\\":\\\"dst_ip\\\",\\\"boost\\\":1}},{\\\"exists\\\":{\\\"field\\\":\\\"dst_port\\\",\\\"boost\\\":1}},{\\\"exists\\\":{\\\"field\\\":\\\"dst_db_name\\\",\\\"boost\\\":1}},{\\\"exists\\\":{\\\"field\\\":\\\"dst_db_table\\\",\\\"boost\\\":1}},{\\\"exists\\\":{\\\"field\\\":\\\"dst_asset_name\\\",\\\"boost\\\":1}

    2024年02月08日
    浏览(30)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包