EasyExcel

EasyExcel

官方文档

EasyExcel官方文档 - 基于Java的Excel处理工具 | Easy Excel (alibaba.com)

优势

Java解析、生成Excel比较有名的框架有Apache poi、jxl。但他们都存在一个严重的问题就是非常的耗内存 ,poi有一套SAX模式的API可以一定程度的解决一些内存溢出的问题,但POI还是有一些缺陷,比如07版Excel解压缩以及解压后存储都是在内存中完成的,内存消耗依然很大。一旦并发上来后一定会OOM或者JVM频繁的full gc.

easyexcel重写了poi对07版Excel的解析,一个3M的excel用POI sax解析依然需要100M左右内存,改用easyexcel可以降低到几M,并且再大的excel也不会出现内存溢出;03版依赖POI的sax模式,在上层做了模型转换的封装,让使用者更加简单方便。

代码示例

关于Easyexcel | Easy Excel (alibaba.com)

excel转json数据

  1. 引入easy excel依赖

    xml 复制代码
            <!-- easy excel -->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>easyexcel</artifactId>
                <version>3.3.2</version>
            </dependency>
  2. 编写controller

    java 复制代码
    package com.junfeng.tool.controller;
    
    import com.alibaba.excel.EasyExcel;
    import com.alibaba.fastjson.JSON;
    import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
    import com.github.xiaoymin.knife4j.annotations.ApiSupport;
    import com.junfeng.tool.config.EasyExcelListener;
    import io.swagger.annotations.Api;
    import io.swagger.annotations.ApiOperation;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.multipart.MultipartFile;
    
    import java.io.IOException;
    import java.util.List;
    import java.util.Map;
    
    /***
     * @Author junfeng
     */
    @Api(tags = "excel")
    @ApiSupport(author = "1033110136@qq.com", order = 1)
    @RestController
    @RequestMapping("/api/excel")
    @Slf4j
    public class  ExcelController {
    
    
        @ApiOperationSupport(author = "junfeng")
        @ApiOperation(value = "excel转换json")
        @PostMapping("/upload")
        public Object upload(@RequestParam("file") MultipartFile file) throws IOException {
            // 读取Excel
            EasyExcel.read(file.getInputStream(), new EasyExcelListener()).sheet().headRowNumber(1).doRead();
    
            // 从监听中获取结果集
            List<Map<String, Object>> importList = EasyExcelListener.dataList;
            log.info("导入集合 list = {}", JSON.toJSON(importList));
    
            return JSON.toJSON(importList);
        }
    
    
    }
  3. 监听器

    java 复制代码
    package com.junfeng.tool.config;
    
    import com.alibaba.excel.context.AnalysisContext;
    import com.alibaba.excel.event.AnalysisEventListener;
    import lombok.extern.slf4j.Slf4j;
    
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    @Slf4j
    public class EasyExcelListener extends AnalysisEventListener<Map<String, Object>> {
    
        private Map<Integer, String> headMap;
    
        public static final List<Map<String, Object>> dataList = new ArrayList<>();
    
        @Override
        public void invoke(Map<String, Object> data, AnalysisContext context) {
            //把表头和值放入Map
            HashMap<String, Object> paramsMap = new HashMap<>();
            for (int i = 0; i < data.size(); i++) {
                String key = headMap.get(i);
                Object value = data.get(i);
                //将表头作为map的key,每行每个单元格的数据作为map的value
                paramsMap.put(key, value);
                dataList.add(paramsMap);
            }
        }
    
        @Override
        public void doAfterAllAnalysed(AnalysisContext context) {
    
        }
    
        @Override
        public void invokeHeadMap(Map<Integer, String> head, AnalysisContext context) {
            headMap = head;
        }
    
    
    }

重点代码解析

复制代码
public abstract class AnalysisEventListener<T> implements ReadListener<T> {
    public AnalysisEventListener() {
    }

    public void invokeHead(Map<Integer, ReadCellData<?>> headMap, AnalysisContext context) {
        this.invokeHeadMap(ConverterUtils.convertToStringMap(headMap, context), context);
    }

    public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
    }
}
java 复制代码
public interface ReadListener<T> extends Listener {
    default void onException(Exception exception, AnalysisContext context) throws Exception {
        throw exception;
    }

    default void invokeHead(Map<Integer, ReadCellData<?>> headMap, AnalysisContext context) {
    }

    void invoke(T var1, AnalysisContext var2);

    default void extra(CellExtra extra, AnalysisContext context) {
    }

    void doAfterAllAnalysed(AnalysisContext var1);

    default boolean hasNext(AnalysisContext context) {
        return true;
    }
}

如下图EasyExcelListener继承AnalysisEventListener实现接口ReadListener

ReadListener中有三个重要接口

invokeHead:解析标题头的数据

invoke:这个每一条数据解析都会来调用,这里可以将数据存到list集合里面,给外部调用。

doAfterAllAnalysed:所有数据解析完成了 都会来调用,这里可以写保存数据库的逻辑

相关推荐
不吃洋葱.1 天前
Bean.
java·开发语言
送秋三十五1 天前
spring源码分析————ListableBeanFactory
java·后端·spring
努力也学不会java1 天前
【设计模式】状态模式
java·设计模式·状态模式
.豆鲨包1 天前
【设计模式】单例模式
java·单例模式·设计模式
邂逅星河浪漫1 天前
【Docker+Nginx+Ollama】前后端分离式项目部署(传统打包方式)
java·nginx·docker·部署
IAtlantiscsdn1 天前
Redis Stack扩展功能
java·数据库·redis
yunmi_1 天前
2024版 IDEA 用 Maven 创建 java 项目(+Maven 安装和配置)
java·maven
float_六七1 天前
Spring事务注解@Transactional核心机制详解
java·后端·spring
渣哥1 天前
Java 线程安全详解:定义、常见问题与解决方案
java
没有bug.的程序员1 天前
Redis 大 Key 与热 Key:生产环境的风险与解决方案
java·数据库·redis·缓存·热key·大key