SpringBoot 使用 EasyExcel 实现Excel文件的导入导出

1. EasyExcel介绍

EasyExcel 是阿里巴巴开源的一个excel处理框架,以使用简单、节省内存著称。EasyExcel 能大大减少占用内存的主要原因是在解析Excel时没有将文件数据一次性全部加载到内存中,而是从磁盘上一行行读取数据,逐个解析。

2. EasyExcel特点

  • Java 领域解析、生成 Excel 比较有名的框架有 Apache poi、jxl 等。但他们都存在一个严重的问题就是非常的耗内存。如果你的系统并发量不大的话可能还行,但是一旦并发上来后一定会OOM(Out Of Memory) 或者 JVM 频繁的 full gc(垃圾回收)。
  • EasyExcel 采用一行一行的解析模式,并将一行的解析结果以观察者的模式通知处理(AnalysisEventListener)
  • EasyExcel 是一个基于Java的简单、省内存的读写 Excel 的开源项目。在尽可能节约内存的情况下支持读写百M的Excel。
  • EasyExcel 与 Apache poi 对比

EasyExcel

Apache poi

一行一行进行解析

一次性把所有数据加载到内存中,进行解析

查询方便

添加、修改、删除方便

3. Excel术语介绍

  • 整个 excel 称为 workbook
  • 每个 workbook 里面有很多 sheet
  • 在每个 sheet 里面有行、列、单元格

4. EasyExcel写操作

(1)pom中引入xml相关依赖


    
    
        com.alibaba
        easyexcel
        2.1.1
    

(2)创建实体类,和excel对应

设置表头和添加的数据字段

@Data
public class Student {
    //设置表头名称
    @ExcelProperty("学生编号")
    private int sno;
    //设置表头名称
    @ExcelProperty("学生姓名")
    private String sname;
}

(3)实现写操作

创建方法循环设置要添加到Excel的数据:

//循环设置要添加的数据,最终封装到list集合中
private static List data() {
    List list = new ArrayList();
    for (int i = 0; i < 10; i++) {
        Student student = new Student();
        student.setSno(i);
        student.setSname("张三"+i);
        list.add(student);
    }
    return list;
}

(4)实现最终的添加操作:

public static void main(String[] args) throws Exception {
    // 写法1
    String fileName = "D:\test01.xlsx";
    // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
    // 如果这里想使用03 则 传入excelType参数即可
    EasyExcel.write(fileName, Student.class).sheet("写入方法").doWrite(data());
}

(5)结果:

SpringBoot 使用 EasyExcel 实现Excel文件的导入导出_第1张图片

5. EasyExcel读操作

(1)创建实体类,和excel对应

@Data
public class Student {
    //设置表头名称
    //设置列对应的属性
	// index = 0 表示第一列
	// index = 1 表示第二列
    @ExcelProperty(value = "学生编号",index = 0)
    private int sno;
    
    @ExcelProperty(value = "学生姓名",index = 1)
    private String sname;
}

(2)创建读取操作的监听器

public class ExcelListener extends AnalysisEventListener {
    //创建list集合封装最终的数据
    List list = new ArrayList();
    //一行一行去读取excle内容
    @Override
    public void invoke(Student student, AnalysisContext analysisContext) {
        System.out.println("***"+student);
        list.add(student);
    }
    //读取excel表头信息
    @Override
    public void invokeHeadMap(Map headMap, AnalysisContext context) {
        System.out.println("表头信息:"+headMap);
    }
    //读取完成后执行
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
    }
}

(3)调用实现最终的读取

 public static void main(String[] args) throws Exception {
        String fileName = "D:\test01.xlsx";
        // 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
        EasyExcel.read(fileName, Student.class, new ExcelListener()).sheet().doRead();
}

(4)结果:

SpringBoot 使用 EasyExcel 实现Excel文件的导入导出_第2张图片

6. Excel文件导入导出逻辑

(1)导出逻辑

public void exportData(HttpServletResponse response) {
        try {
            // 设置下载信息
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            // 这里URLEncoder.encode可以防止中文乱码 当然这和easyexcel没有关系
            String fileName = URLEncoder.encode("课程分类", "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename="+ fileName + ".xlsx");

            // 查询课程分类表所有数据
            List dictList = baseMapper.selectList(null);

            // 将Subject-->SubjectEeVo
            List dictVoList = new ArrayList<>(dictList.size());
            for(Subject dict : dictList) {
                SubjectEeVo dictVo = new SubjectEeVo();
                BeanUtils.copyProperties(dict,dictVo);
                dictVoList.add(dictVo);
            }
            // 用EasyExcel写操作
            EasyExcel.write(response.getOutputStream(), SubjectEeVo.class).sheet("课程分类").doWrite(dictVoList);
        } catch (IOException e) {
            e.printStackTrace();
            throw new GgktException(20001, "导出失败");
        }
    }

以上用到的两个实体信息:

@Data
@ApiModel(description = "Subject")
@TableName("subject")
public class Subject {

	private static final long serialVersionUID = 1L;
	@ApiModelProperty(value = "id")
	private Long id;

	@ApiModelProperty(value = "创建时间")
	@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
	@TableField("create_time")
	private Date createTime;

	@ApiModelProperty(value = "更新时间")
	@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
	@TableField("update_time")
	private Date updateTime;

	@ApiModelProperty(value = "逻辑删除(1:已删除,0:未删除)")
	@JsonIgnore
	@TableLogic
	@TableField("is_deleted")
	private Integer isDeleted;

	@ApiModelProperty(value = "其他参数")
	@TableField(exist = false)
	private Map param = new HashMap<>();

	@ApiModelProperty(value = "类别名称")
	@TableField("title")
	private String title;

	@ApiModelProperty(value = "父ID")
	@TableField("parent_id")
	private Long parentId;

	@ApiModelProperty(value = "排序字段")
	@TableField("sort")
	private Integer sort;

	@ApiModelProperty(value = "是否包含子节点")
	@TableField(exist = false) // 表示表里面没有这个字段,但是这个属性要用到
	private boolean hasChildren;

}
@Data
public class SubjectEeVo {

	@ExcelProperty(value = "id" ,index = 0)
	private Long id;

	@ExcelProperty(value = "课程分类名称" ,index = 1)
	private String title;

	@ExcelProperty(value = "上级id" ,index = 2)
	private Long parentId;

	@ExcelProperty(value = "排序" ,index = 3)
	private Integer sort;


}

(2)导入逻辑:

  创建读取监听器:

@Component
public class SubjectListener extends AnalysisEventListener {
    @Autowired
    private SubjectMapper subjectMapper;
    //一行一行读取
    @Override
    public void invoke(SubjectEeVo subjectEeVo, AnalysisContext analysisContext) {
        //调用方法添加数据库
        Subject subject = new Subject();
        BeanUtils.copyProperties(subjectEeVo,subject);
        subjectMapper.insert(subject);
    }
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
    }
}
@Autowired
private SubjectListener subjectListener;

//导入
@Override
public void importData(MultipartFile file) {
    try {
        EasyExcel.read(file.getInputStream(),
                       SubjectEeVo.class,subjectListener).sheet().doRead();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

你可能感兴趣的:(java,spring,boot,EasyExcel,Excel导入导出)