EasyExcel相关

1. easyexcel--100M

EasyExcel是一个基于Java的使用简单、节省内存的读写Excel的开源项目。在尽可能节约内存的情况下支持读写百M的Excel。

节省内存的原因:在解析Excel时没有将文件数据一次性全部加载到内存中,而是从磁盘上一行行读取数据,逐个解析

EasyExcel采用一行一行的解析模式,并将一行的解析结果以观察者的模式通知处理

通过Java代码完成对Excel的读写操作。所谓的读写理解为上传和下载

github地址:https://github.com/alibaba/easyexcel

官方文档:https://www.yuque.com/easyexcel/doc

2. easyexcel写操作

所谓的写操作,就是把Java中的类对象写入到excel表格中

实现步骤

  1. 引入依赖
xml 复制代码
<dependency>
            <groupId>repMaven.com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>3.0.5</version>
        </dependency>
  1. 封装相应的对象,创建与表格对应的实体类

    java 复制代码
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class ExcelDemo {
        @ExcelProperty(value = "姓名")//标记excel的表头内容
        public String name;
        @ExcelProperty(value = "年龄")
        public Integer age;
        @ExcelProperty(value = "性别")
        public String sex;
        @ExcelIgnore//写入excel表格时忽略该属性
        public String address;
    }
    1. @ExcelProperty:标记excel的表头内容
    2. @ExcelIgnore:在写入excel表格时忽略该属性
  2. 通过easyexcel完成写入操作

    java 复制代码
    public class WriteExcel {
        public static void main(String[] args) {
            //fileName:表示excel写入的路径以及名称
            String fileName="D:\\idea\\easyexcel_demo1\\writer.xlsx";
            //这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板,然后文件流会自动关闭
            //如果这里使用03,则 传入 excelType 参数即可
            List<ExcelDemo> list=new ArrayList<>();
            list.add(new ExcelDemo("章三",18,"男","郑州"));
            list.add(new ExcelDemo("李斯",19,"男","郑州"));
            list.add(new ExcelDemo("汪芜",20,"女","郑州"));
            list.add(new ExcelDemo("码字",25,"男","郑州"));
            EasyExcel.write(fileName,ExcelDemo.class).sheet("第一次完成写操作").doWrite(list);
        }
    }
    1. 准备文件路径
    2. 写出文件

3. easyexcel写操作------web模式【导出】

导出:需要将数据库里面的文件以附件的形式下载到本地电脑,需要参数为response对象,返回值类型为void

  • 实例
java 复制代码
@Controller
public class ExcelController {
    @GetMapping("download")
    public void download(HttpServletResponse response) throws IOException {
        // 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postman
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
        String fileName = URLEncoder.encode("测试", "UTF-8").replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");

        List<ExcelDemo> list=new ArrayList<>();
        list.add(new ExcelDemo("章三",18,"男","郑州"));
        list.add(new ExcelDemo("李斯",19,"男","郑州"));
        list.add(new ExcelDemo("汪芜",20,"女","郑州"));
        list.add(new ExcelDemo("码字",25,"男","郑州"));
        EasyExcel.write(response.getOutputStream(), ExcelDemo.class).sheet("模板").doWrite(list);
    }
}

也可以在controllre层仅进行调用操作,将逻辑交由service去做,即:

  • controller
java 复制代码
    @ApiOperation("导出")
    @GetMapping("/download")
    public void exportData(HttpServletResponse response){
        dictService.exportData(response);
    }
  • service
java 复制代码
 @Override
    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<Dict> list = this.baseMapper.selectList(null);
            //转换文件
            ArrayList<DictEeVo> dictEeVos = new ArrayList<>();
            for (Dict dict : list) {
                DictEeVo dictEeVo = new DictEeVo();
                //转换
                BeanUtils.copyProperties(dict, dictEeVo);
                //添加
                dictEeVos.add(dictEeVo);
            }
            //写出
              EasyExcel.write(response.getOutputStream(), DictEeVo.class).sheet("数据字典").doWrite(dictEeVos);
          } catch (Exception e) {
              e.printStackTrace();
        }
    }

测试

测试仅需允许项目,然后在前端页面写入实际的url地址即可,也可以添加按钮的点击事件进行测试

4. easyexcel读操作

  • 流程
  • 实现步骤
  1. 引入fastjson依赖

    xml 复制代码
    <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>1.2.83</version>
            </dependency>

    com.alibaba.fastjson.JSON是阿里巴巴开源的一个高性能数据交换格式库,它是基于Java语言的JSON解析和生成工具。Fastjson旨在提供一种快速、便捷的方式来序列化和反序列化Java对象到JSON字符串,以及将JSON字符串转换回Java对象。它支持大数据量的处理,并且具有优秀的性能,通常比标准的Java自带的java.util.JSONObjectorg.json.JSONObject更快。

    使用Fastjson的好处包括:

    1. 高效:通过字节码操作,使得JSON解析和生成的速度非常快。
    2. 易用:API设计简洁明了,易于理解和上手。
    3. 功能丰富:支持复杂数据结构的处理,如日期、数组、集合等。

    在Java项目中,你可以通过Maven或Gradle添加fastjson依赖来使用它,然后通过JSONObjectJSONArray或其他类来进行JSON相关的操作。

  2. 创建监听器

    java 复制代码
    package com.zmq.excel;
    
    import com.alibaba.excel.context.AnalysisContext;
    import com.alibaba.excel.read.listener.ReadListener;
    import com.alibaba.excel.util.ListUtils;
    import com.alibaba.fastjson.JSON;
    import lombok.extern.slf4j.Slf4j;
    
    import java.util.List;
    
    // 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
    @Slf4j
    public class DemoDataListener implements ReadListener<ExcelDemo> {
    
        /**
         * 每隔5条存储数据库,实际使用中可以100条,然后清理list ,方便内存回收
         */
        private static final int BATCH_COUNT = 100;
        /**
         * 缓存的数据
         */
        private List<ExcelDemo> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
        /**
         * 假设这个是一个DAO,当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象没用。
         */
        private DemoDAO demoDAO;
    
        public DemoDataListener() {
            // 这里是demo,所以随便new一个。实际使用如果到了spring,请使用下面的有参构造函数
            demoDAO = new DemoDAO();
        }
    
        /**
         * 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来
         *
         * @param demoDAO
         */
        public DemoDataListener(DemoDAO demoDAO) {
            this.demoDAO = demoDAO;
        }
    
        /**
         * 这个每一条数据解析都会来调用
         *
         * @param data    one row value. Is is same as {@link AnalysisContext#readRowHolder()}
         * @param context
         */
        //一行一行的去读取里面的数据
        @Override
        public void invoke(ExcelDemo data, AnalysisContext context) {
            log.info("解析到一条数据:{}", JSON.toJSONString(data));
            cachedDataList.add(data);
            // 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
            if (cachedDataList.size() >= BATCH_COUNT) {
                saveData();
                // 存储完成清理 list
                cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
            }
        }
    
        /**
         * 所有数据解析完成了 都会来调用
         *
         * @param context
         */
        @Override
        public void doAfterAllAnalysed(AnalysisContext context) {
            // 这里也要保存数据,确保最后遗留的数据也存储到数据库
            saveData();
            log.info("所有数据解析完成!");
        }
    
        /**
         * 加上存储数据库
         */
        private void saveData() {
            log.info("{}条数据,开始存储数据库!", cachedDataList.size());
            demoDAO.save(cachedDataList);
            log.info("存储数据库成功!");
        }
    }

    进行读操作时就会触发监听器,基本不需要改动

  3. dao

    java 复制代码
    package com.zmq.excel;
    
    import java.util.List;
    
    /**
     * 假设这个是你的DAO存储。当然还要这个类让spring管理,当然你不用需要存储,也不需要这个类。
     **/
    public class DemoDAO {
        public void save(List<ExcelDemo> list) {
            // 如果是mybatis,尽量别直接调用多次insert,自己写一个mapper里面新增一个方法batchInsert,所有数据一次性插入
        }
    }

    dao中填写需要的操作

  4. 读取

    java 复制代码
    public class ReadExcel {
        public static void main(String[] args) {
            /**
             * 指定列的下标或者列名
             *
             * <p>1. 创建excel对应的实体对象,并使用{@link ExcelProperty}注解. 参照{@link IndexOrNameData}
             * <p>2. 由于默认一行行的读取excel,所以需要创建excel一行一行的回调监听器,参照{@link IndexOrNameDataListener}
             * <p>3. 直接读即可
             */
    
            //fileName:表示excel读取的路径以及名称
            String fileName="D:\\idea\\easyexcel_demo1\\writer.xlsx";
            // 这里默认读取第一个sheet
            //new DemoDataListener():监听器
            EasyExcel.read(fileName, ExcelDemo.class, new DemoDataListener()).sheet().doRead();
        }
    }

5. easyexcel文件上传-web【导入】

导入:需要将本地文件插入到数据库,参数:multiparefile,返回值:"成功或失败"

使用excel进行导入需要解析器的配合,使用监听器对读取的文件进行操作

解析器:用来读取文件,并将数据插入到数据库

  1. 加入文件上传的依赖

    xml 复制代码
     <dependency>
                <groupId>repMaven.commons-fileupload</groupId>
                <artifactId>commons-fileupload</artifactId>
                <version>1.4</version>
            </dependency>

    commons-fileupload是一个开源库,专为Java应用程序设计,用于处理文件上传功能。它简化了处理HTTP请求中的multipart/form-data格式,这种格式通常用于用户通过Web表单上传文件到服务器。该库提供了一组工具类和处理器,使得开发者能够解析上传的文件流,并管理文件名、大小限制等复杂操作。它的API易于使用,支持断点续传以及错误处理,广泛应用于web应用开发中的文件上传组件。

  2. 文件上传解析器------spring配置文件中

    若使用springboot框架,仅引入上述依赖即可

    xml 复制代码
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
            <property name="maxUploadSize" value="1000000000"/>
        </bean>
  3. controller

    java 复制代码
    @Autowired
        private DemoDAO demoDAO;
        @PostMapping("/upload")
        @ResponseBody //将返回值转化为json格式
        public String upload(MultipartFile file) throws IOException{
            EasyExcel.read(file.getInputStream(), ExcelDemo.class, new DemoDataListener(demoDAO)).sheet().doRead();
            return "success";
        }

    DemoDao层加入注入spring容器的注解:@Component

  4. 测试------使用postman完成测试

相关推荐
8***84822 分钟前
spring security 超详细使用教程(接入springboot、前后端分离)
java·spring boot·spring
9***J6284 分钟前
Spring Boot项目集成Redisson 原始依赖与 Spring Boot Starter 的流程
java·spring boot·后端
M***Z21016 分钟前
SQL 建表语句详解
java·数据库·sql
v***79416 分钟前
Spring Boot 热部署
java·spring boot·后端
执笔论英雄16 分钟前
【RL】python协程
java·网络·人工智能·python·设计模式
galaxyffang27 分钟前
认证、会话管理、授权的区别
java
未名编程31 分钟前
Windows 下如何部署 Nacos 并导入配置文件
java·windows
boonya37 分钟前
Java中Plugin设计模式的规范应用
java·spring·设计模式·插件模式
杰克尼1 小时前
3. 分巧克力
java·数据结构·算法
听风吟丶1 小时前
Java 高级多线程编程:从虚拟线程到结构化并发的实战演进
java·开发语言