阅读 304

SpringBoot整合EasyExcel的完整过程记录

easyexcel是阿里巴巴旗下开源项目,主要用于Excel文件的导入和导出处理,下面这篇文章主要给大家介绍了关于SpringBoot整合EasyExcel的完整过程,需要的朋友可以参考下

目录
  • 为什么要用EasyExcel

  • 1.EasyExcel简介

  • 2.使用EasyExcel实现写

    • 2.1 创建实体类

    • 2.2 测试写Excel

  • 3.使用EasyExcel实现读

    • 3.1 创建读取操作的监听器

    • 3.2 测试读Excel

  • 4.springboot项目实践EasyExcel

    • 4.1 pom中引入相关依赖

    • 4.2 创建数据库表及添加数据

    • 4.3 实体类

    • 4.4 Controller层

    • 4.5 Service层

    • 4.6 创建监听器(核心部分)

    • 4.7 结果展示

  • 总结

    为什么要用EasyExcel

    由于apache poi和jxl,excelPOI都有一个严重的问题,就是非常消耗内存,特别处理数据量多时,速度慢并且时有异常发生,所以改用由阿里研发的easyExcel更可靠一些,它的官方建议对于1000行以内的采用原来poi的写法一次读写,但于1000行以上的数据,有用了一行行进行解析的方案,这样避免了内存的溢出。

    1.EasyExcel简介

    • Java领域解析、生成Excel比较有名的框架有Apache poi、jxl等。但他们都存在一个严重的问题就是非常的耗内存。如果你的系统并发量不大的话可能还行,但是一旦并发上来后一定会OOM或 者JVM频繁的full gc。

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

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

    2.使用EasyExcel实现写

    2.1 创建实体类

    创建与Excel对应的实体类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    /**
     * @author xppll
     * @date 2021/12/3 10:05
     */
    @Data
    public class DemoData {
        //设置excel表头名称,index表示对应的第几列
        @ExcelProperty(value = "学生编号",index = 0)
        private Integer sno;
     
        @ExcelProperty(value = "学生姓名",index = 1)
        private String sname;
    }

    ExcelProperty:指定当前字段对应excel中的那一列。可以根据名字或者Index去匹配。当然也可以不写,默认第一个字段就是index=0,以此类推。

    2.2 测试写Excel

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    /**
     * @author xppll
     * @date 2021/12/3 10:08
     */
    public class TestWriteExcel {
        public static void main(String[] args) {
            //实现excel写的操作
            //1.设置写入文件夹的地址和excel文件名称
            String fileName = "D:\\write.xlsx";
     
            //2.调用easyexcel里面方法实现写操作
            //传入:文件存放的路径+对应的实体类class
            EasyExcel.write(fileName, DemoData.class).sheet("学生列表").doWrite(getData());
        }
     
        //创建方法返回list集合(测试数据)
        private static List<DemoData> getData() {
            List<DemoData> list = new ArrayList<>();
            for (int i = 0; i < 10; i++) {
                DemoData data = new DemoData();
                data.setSno(i);
                data.setSname("lucy" + i);
                list.add(data);
            }
            return list;
        }
    }

    结果如下

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R51xa0VB-1638630992973)(SpringBoot项目整合EasyExcel.assets/image-20211203105225367.png)]

    3.使用EasyExcel实现读

    3.1 创建读取操作的监听器

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    /**
     * @author xppll
     * @date 2021/12/3 10:29
     */
    public class ExcelListener extends AnalysisEventListener<DemoData> {
        /**
         * 一行一行读取Excel中的内容
         *
         * @param data
         * @param analysisContext
         */
        @Override
        public void invoke(DemoData data, AnalysisContext analysisContext) {
            System.out.println("****" + data);
        }
     
     
        /**
         * 读取表头
         * @param headMap
         * @param context
         */
        @Override
        public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
            System.out.println("表头:"+headMap);
        }
     
        /**
         * 读取完成之后做的事
         *
         * @param analysisContext
         */
        @Override
        public void doAfterAllAnalysed(AnalysisContext analysisContext) {
     
        }
    }

    3.2 测试读Excel

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    /**
     * @author xppll
     * @date 2021/12/3 10:35
     */
    public class TestReadExcel {
        public static void main(String[] args) {
            //读取文件的路径
            String fileName = "D:\\write.xlsx";
            //传入三个参数:文件路径+封装的类的class+监听器
            EasyExcel.read(fileName, DemoData.class,new ExcelListener())
                .sheet()
                .doRead();
        }
    }

    控制台输出如下

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ugT2UNpq-1638630992975)(SpringBoot项目整合EasyExcel.assets/image-20211203105451947.png)]

    4.springboot项目实践EasyExcel

    通过在后台管理上传excel文件添加课程分类(一共两级分类)


    4.1 pom中引入相关依赖

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

    4.2 创建数据库表及添加数据

    这里创建一个课程表用EasyExcel实现课程的分类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    CREATE TABLE `edu_subject` (
      `id` char(19) NOT NULL COMMENT '课程类别ID',
      `title` varchar(10) NOT NULL COMMENT '类别名称',
      `parent_id` char(19) NOT NULL DEFAULT '0' COMMENT '父ID',
      `sort` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '排序字段',
      `gmt_create` datetime NOT NULL COMMENT '创建时间',
      `gmt_modified` datetime NOT NULL COMMENT '更新时间',
      PRIMARY KEY (`id`),
      KEY `idx_parent_id` (`parent_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=COMPACT COMMENT='课程科目';
    1
    INSERT INTO `edu_subject` VALUES ('1178214681118568449','后端开发','0',1,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681139539969','Java','1178214681118568449',1,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681181483010','前端开发','0',3,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681210843137','JavaScript','1178214681181483010',4,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681231814658','云计算','0',5,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681252786178','Docker','1178214681231814658',5,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681294729217','Linux','1178214681231814658',6,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681324089345','系统/运维','0',7,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681353449473','Linux','1178214681324089345',7,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681382809602','Windows','1178214681324089345',8,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681399586817','数据库','0',9,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681428946945','MySQL','1178214681399586817',9,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681454112770','MongoDB','1178214681399586817',10,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681483472898','大数据','0',11,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681504444418','Hadoop','1178214681483472898',11,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681529610242','Spark','1178214681483472898',12,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681554776066','人工智能','0',13,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681584136193','Python','1178214681554776066',13,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681613496321','编程语言','0',14,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681626079234','Java','1178214681613496321',14,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178585108407984130','Python','1178214681118568449',2,'2019-09-30 16:19:22','2019-09-30 16:19:22'),('1178585108454121473','HTML/CSS','1178214681181483010',3,'2019-09-30 16:19:22','2019-09-30 16:19:22');

    4.3 实体类

    1
    2
    3
    4
    5
    6
    7
    @Data
    public class SubjectData {
        @ExcelProperty(index = 0)
        private String oneSubjectName;
        @ExcelProperty(index = 1)
        private String twoSubjectName;
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    /**
     * 课程科目
     * @author xppll
     * @since 2021-12-03
     */
    @Data
    @EqualsAndHashCode(callSuper = false)
    @Accessors(chain = true)
    @ApiModel(value="EduSubject对象", description="课程科目")
    public class EduSubject implements Serializable {
     
        private static final long serialVersionUID = 1L;
     
        @ApiModelProperty(value = "课程类别ID")
        @TableId(value = "id", type = IdType.ID_WORKER_STR)
        private String id;
     
        @ApiModelProperty(value = "类别名称")
        private String title;
     
        @ApiModelProperty(value = "父ID")
        private String parentId;
     
        @ApiModelProperty(value = "排序字段")
        private Integer sort;
     
        @ApiModelProperty(value = "创建时间")
        @TableField(fill = FieldFill.INSERT)
        private Date gmtCreate;
     
        @ApiModelProperty(value = "更新时间")
        @TableField(fill = FieldFill.INSERT_UPDATE)
        private Date gmtModified;
    }

    4.4 Controller层

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    @Autowired
    private EduSubjectService subjectService;
     
    //添加课程分类
    //获取前端上传过来的excel文件,把文件内容读取出来保存到数据库
    @PostMapping("addSubject")
    public R addSubject(MultipartFile file){
     
        subjectService.saveSubject(file,subjectService);
        return R.ok();
    }

    4.5 Service层

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    //添加课程分类
    @Override
    public void saveSubject(MultipartFile file, EduSubjectService subjectService) {
        try {
            //得到文件的输入流
            InputStream in = file.getInputStream();
            //调用方法进行读取
            EasyExcel.read(in, SubjectData.class, new SubjectExcelListener(subjectService)).sheet().doRead();
     
        } catch (Exception e) {
            e.printStackTrace();
        }
     
    }

    4.6 创建监听器(核心部分)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    /**
     * @author xppll
     * @date 2021/12/3 12:02
     */
    @Component
    public class SubjectExcelListener extends AnalysisEventListener<SubjectData> {
     
        public EduSubjectService subjectService;
     
        public SubjectExcelListener(EduSubjectService subjectService) {
            this.subjectService = subjectService;
        }
     
        public SubjectExcelListener() {
        }
     
        //读取excel内容,一行一行读取
        @Override
        public void invoke(SubjectData subjectData, AnalysisContext analysisContext) {
            if (subjectData == null) {
                throw new GuliException(20001, "文件数据为空");
            }
            //一行一行读取,第一个值为一级分类,第二个值为二级分类
     
            //先判断一级分类是否重复
            EduSubject existOneSubject = this.existOneSubject(subjectData.getOneSubjectName(), subjectService);
            //没有相同的一级分类
            if(existOneSubject==null){
                existOneSubject=new EduSubject();
                existOneSubject.setParentId("0");
                existOneSubject.setTitle(subjectData.getOneSubjectName());
                subjectService.save(existOneSubject);
            }
     
            //获取一级分类的id值
            String pid=existOneSubject.getId();
     
            //判断二级分类是否重复
            EduSubject existTwoSubject = this.existTwoSubject(subjectData.getTwoSubjectName(), subjectService, pid);
            if(existTwoSubject==null){
                existTwoSubject=new EduSubject();
                existTwoSubject.setParentId(pid);
                existTwoSubject.setTitle(subjectData.getTwoSubjectName());
                subjectService.save(existTwoSubject);
            }
        }
     
        //判断一级分类不能重复添加
        private EduSubject existOneSubject(String name, EduSubjectService subjectService) {
            LambdaQueryWrapper<EduSubject> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(EduSubject::getTitle, name)
                .eq(EduSubject::getParentId, "0");
            EduSubject oneSubject = subjectService.getOne(queryWrapper);
            return oneSubject;
        }
        //判断二级分类不能重复添加
        private EduSubject existTwoSubject(String name, EduSubjectService subjectService,String pid) {
            LambdaQueryWrapper<EduSubject> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(EduSubject::getTitle, name)
                .eq(EduSubject::getParentId, pid);
            EduSubject twoSubject = subjectService.getOne(queryWrapper);
            return twoSubject;
        }
        @Override
        public void doAfterAllAnalysed(AnalysisContext analysisContext) {
     
        }
    }

    4.7 结果展示

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z8EaQ0N5-1638630992977)(SpringBoot项目整合EasyExcel.assets/image-20211204085942730.png)]

    Excel模板如下

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qndFFrE1-1638630992978)(SpringBoot项目整合EasyExcel.assets/image-20211204090109056.png)]

    上传后数据库数据如下

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aNvpC981-1638630992980)(SpringBoot项目整合EasyExcel.assets/image-20211204090423680.png)]

    如果想要详细使用可以参考官方文档:EasyExcel

    总结

    到此这篇关于SpringBoot整合EasyExcel的文章就介绍到这了

    原文链接:https://blog.csdn.net/qq_45966440/article/details/121723600


    文章分类
    代码人生
    版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
    相关推荐