为解决大数据量的excel文档导入导出存在的内存泄露问题,可使用EasyExcel实现excel文档的解析和生成。

配置

  1. <dependency>
  2. <groupId>com.alibaba</groupId>
  3. <artifactId>easyexcel</artifactId>
  4. <version>2.2.6</version>
  5. </dependency>

使用

excel导出

  • 代码示例
    • Customer.java(vo) ```java package org.polaris.easyexcel.vo;

public class Customer {

  1. private int index;
  2. private String company;
  3. private String type;
  4. private int cash;
  5. private String from;
  6. private String others;
  7. public Customer(int index, String company, String type, int cash, String from, String others) {
  8. this.index = index;
  9. this.company = company;
  10. this.type = type;
  11. this.cash = cash;
  12. this.from = from;
  13. this.others = others;
  14. }
  15. public int getIndex() {
  16. return index;
  17. }
  18. public void setIndex(int index) {
  19. this.index = index;
  20. }
  21. public String getCompany() {
  22. return company;
  23. }
  24. public void setCompany(String company) {
  25. this.company = company;
  26. }
  27. public String getType() {
  28. return type;
  29. }
  30. public void setType(String type) {
  31. this.type = type;
  32. }
  33. public int getCash() {
  34. return cash;
  35. }
  36. public void setCash(int cash) {
  37. this.cash = cash;
  38. }
  39. public String getFrom() {
  40. return from;
  41. }
  42. public void setFrom(String from) {
  43. this.from = from;
  44. }
  45. public String getOthers() {
  46. return others;
  47. }
  48. public void setOthers(String others) {
  49. this.others = others;
  50. }
  51. @Override
  52. public String toString() {
  53. return "Customer{" +
  54. "index=" + index +
  55. ", company='" + company + '\'' +
  56. ", type='" + type + '\'' +
  57. ", cash=" + cash +
  58. ", from='" + from + '\'' +
  59. ", others='" + others + '\'' +
  60. '}';
  61. }

}

  1. - **ExcelExportTest.java(测试类)**
  2. ```java
  3. import com.alibaba.excel.EasyExcel;
  4. import com.alibaba.excel.ExcelWriter;
  5. import com.alibaba.excel.util.DateUtils;
  6. import com.alibaba.excel.write.metadata.WriteSheet;
  7. import org.junit.Test;
  8. import org.polaris.easyexcel.vo.Customer;
  9. import java.io.BufferedOutputStream;
  10. import java.io.File;
  11. import java.io.FileOutputStream;
  12. import java.io.IOException;
  13. import java.util.*;
  14. public class ExcelExportTest
  15. {
  16. @Test
  17. public void excelExport() throws IOException
  18. {
  19. String templateFileName=ExcelExportTest.class.getClassLoader().getResource("template1.xls").getPath();
  20. BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream("output"+ File.separator+"template1-out.xls"));
  21. ExcelWriter excelWriter=EasyExcel.write(bos).withTemplate(templateFileName).build();
  22. WriteSheet writeSheet=EasyExcel.writerSheet().build();
  23. List<Customer> customers=new ArrayList<>();
  24. customers.add(new Customer(1,"广州市越秀区东方红幼儿园","002",1000,"01","测试数据1"));
  25. customers.add(new Customer(2,"广州市越秀区东山幼儿园","002",2000,"01","测试数据2"));
  26. customers.add(new Customer(3,"广州市越秀区太阳升幼儿园","002",3000,"02","测试数据3"));
  27. customers.add(new Customer(4,"广州市越秀区红黑蓝幼儿园","005",4000,"01","测试数据4"));
  28. customers.add(new Customer(5,"广州市越秀区太阳幼儿园","007",5000,"02","测试数据5"));
  29. customers.add(new Customer(6,"广州市越秀区月亮幼儿园","002",6000,"01","测试数据6"));
  30. customers.add(new Customer(7,"广州市越秀区星星幼儿园","002",7000,"01","测试数据7"));
  31. customers.add(new Customer(8,"广州市越秀区星星幼儿园","008",8000,"01","测试数据8"));
  32. excelWriter.fill(customers,writeSheet);
  33. Map<String, Object> maps=new HashMap<>();
  34. maps.put("date",DateUtils.format(new Date(),DateUtils.DATE_FORMAT_19));
  35. excelWriter.fill(maps,writeSheet);
  36. excelWriter.finish();
  37. bos.flush();
  38. bos.close();
  39. }
  40. }
  • 附件

  • 代码示例

    • PayDetail.java(vo) ```java package org.polaris.easyexcel.vo;

/**

  • 缴费明细
  • @author polaris 450733605@qq.com */ public class PayDetail {

    private String id; private String name; private String address; private String area; private String paydate; private String singleAmt; private String totalAmt;

    public String getId() {

    1. return id;

    }

    public void setId(String id) {

    1. this.id = id;

    }

    public String getName() {

    1. return name;

    }

    public void setName(String name) {

    1. this.name = name;

    }

    public String getAddress() {

    1. return address;

    }

    public void setAddress(String address) {

    1. this.address = address;

    }

    public String getArea() {

    1. return area;

    }

    public void setArea(String area) {

    1. this.area = area;

    }

    public String getPaydate() {

    1. return paydate;

    }

    public void setPaydate(String paydate) {

    1. this.paydate = paydate;

    }

    public String getSingleAmt() {

    1. return singleAmt;

    }

    public void setSingleAmt(String singleAmt) {

    1. this.singleAmt = singleAmt;

    }

    public String getTotalAmt() {

    1. return totalAmt;

    }

    public void setTotalAmt(String totalAmt) {

    1. this.totalAmt = totalAmt;

    }

    @Override public String toString() {

    1. return "PayDetail{" +
    2. "id='" + id + '\'' +
    3. ", name='" + name + '\'' +
    4. ", address='" + address + '\'' +
    5. ", area='" + area + '\'' +
    6. ", paydate='" + paydate + '\'' +
    7. ", singleAmt='" + singleAmt + '\'' +
    8. ", totalAmt='" + totalAmt + '\'' +
    9. '}';

    } } ```

    • DataListener.java(vo) ```java package org.polaris.easyexcel.util;

import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.event.AnalysisEventListener; import org.polaris.easyexcel.vo.PayDetail; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.List;

/**

  • 分页监听器
  • @author polaris 450733605@qq.com */ public class DataListener extends AnalysisEventListener {

    private final static Logger log = LoggerFactory.getLogger(DataListener.class);

    List list=new ArrayList<>();

    @Override public void doAfterAllAnalysed(AnalysisContext analysisContext) {

    1. doWork(analysisContext);

    }

    @Override public void invoke(PayDetail payDetail, AnalysisContext analysisContext) {

    1. // 此处进行数据处理
    2. log.info(payDetail.toString());
    3. list.add(payDetail);
    4. // 分批处理从excel文档读取的数据,每次处理若干条数据,防止存储几万条数据在内存,容易OOM
    5. int BATCH_SIZE=32;
    6. if(list.size()>=BATCH_SIZE){
    7. // 每读取${BATCH_SIZE}条数据清空一次列表
    8. doWork(analysisContext);
    9. list.clear();
    10. }

    }

    private void doWork(AnalysisContext analysisContext){

    1. log.info(String.format("当前批次处理数据条数:%d,累计:%d/%d",
    2. list.size(),
    3. analysisContext.getCurrentRowNum(),
    4. analysisContext.getTotalCount()-1)
    5. );

    } } ```

    • ExcelParseTest.java(测试类) ```java package org.polaris.easyexcel;

import com.alibaba.excel.EasyExcel; import com.alibaba.excel.support.ExcelTypeEnum; import org.junit.Test; import org.polaris.easyexcel.util.DataListener; import org.polaris.easyexcel.vo.PayDetail; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.util.List;

/**

  • excel解析示例
  • @author polaris 450733605@qq.com */ public class ExcelParseTest {

    private final static Logger log = LoggerFactory.getLogger(ExcelParseTest.class);

    /**

    • 解析excel
    • @throws IOException */ @Test public void excelParseSimple() throws IOException { InputStream inputStream=new BufferedInputStream(ExcelParseTest.class.getClassLoader().getResourceAsStream(“template2.xlsx”)); List voList=EasyExcel.read(inputStream)

      1. .excelType(ExcelTypeEnum.XLSX)
      2. .head(PayDetail.class)
      3. .sheet()
      4. .headRowNumber(2)
      5. .doReadSync();

      inputStream.close(); for(int i=0;i<voList.size();i++){

      1. log.info(voList.get(i).toString());

      } }

      /**

    • 分页读取Excel文档中的数据
    • @throws IOException / @Test public void excelParseBatch() throws IOException { InputStream inputStream=new BufferedInputStream(ExcelParseTest.class.getClassLoader().getResourceAsStream(“template2.xlsx”)); // 方式1:不推荐,结果将再次封装到${voList},若过大可能导致OOM /List voList=EasyExcel.read(inputStream,new DataListener())

      1. .excelType(ExcelTypeEnum.XLSX)
      2. .head(PayDetail.class)
      3. .sheet()
      4. .headRowNumber(2)
      5. .doReadSync();*/

      // 方式2:推荐,分批处理,不做收集 EasyExcel.read(inputStream,new DataListener())

      1. .excelType(ExcelTypeEnum.XLSX)
      2. .head(PayDetail.class)
      3. .sheet()
      4. .headRowNumber(2)
      5. .doRead();

      inputStream.close();

      log.info(“完成——————————————————“); }

} ```