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:所有数据解析完成了 都会来调用,这里可以写保存数据库的逻辑

相关推荐
Xxxx. .Xxxx13 分钟前
C语言程序设计实验与习题指导 (第4版 )课后题-第二章+第三章
java·c语言·开发语言
姜西西_14 分钟前
[Spring]Spring MVC 请求和响应及用到的注解
java·spring·mvc
逸狼14 分钟前
【JavaEE初阶】多线程6(线程池\定时器)
java·开发语言·算法
qq_353233538916 分钟前
【原创】java+springboot+mysql科研成果管理系统设计与实现
java·spring boot·mysql·mvc·web
dawn19122817 分钟前
SpringMVC 入门案例详解
java·spring·html·mvc
极客先躯18 分钟前
高级java每日一道面试题-2024年9月16日-框架篇-Spring MVC和Struts的区别是什么?
java·spring·面试·mvc·struts2·框架篇·高级java
Counter-Strike大牛19 分钟前
MySQL迁移达梦报错,DMException: 第1 行附近出现错误: 无效的表或视图名[ACT_GE_PROPERTY]
java·数据库
我要学编程(ಥ_ಥ)2 小时前
滑动窗口算法专题(1)
java·数据结构·算法·leetcode
niceffking2 小时前
JVM 一个对象是否已经死亡?
java·jvm·算法
真的很上进2 小时前
【Git必看系列】—— Git巨好用的神器之git stash篇
java·前端·javascript·数据结构·git·react.js