SpringBoot集成EasyExcel的应用场景分析

1、介绍

官网地址:https://www.yuque.com/easyexcel
特点:

1、Java领域解析、生成Excel比较有名的框架有Apache poi、jxl等。但他们都存在一个严重的问题就是 非常的耗内存。如果你的系统并发量不大的话可能还行,但是一旦并发上来后一定会OOM或 者JVM频繁的full gc。
2、EasyExcel是阿里巴巴开源的一个excel处理框架,以使用简单、节省内存著称。EasyExcel能大大减 少占用内存的主要原因是在解析Excel时没有将文件数据一次性全部加载到内存中,而是从磁盘上一 行行读取数据,逐个解析。
3、EasyExcel采用一行一行的解析模式,并将一行的解析结果以观察者的模式通知处理 (AnalysisEventListener)。

2、应用场景

1、数据导入:减轻录入工作量
2、数据导出:统计信息归档
3、数据传输:异构系统之间数据传输

3、要实现的效果

sql

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 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 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=COMPACT COMMENT='课程科目';

转成->

3、使用

3.1、pom依赖导入

温馨提示:以下版本不能更换,换了可能会不行

<dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>2.1.1</version>
        </dependency>
		<!--xls-->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.17</version>
        </dependency>

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.17</version>
        </dependency>

3.2、controller

package com.zhz.serviceedu.controller;

import com.zhz.common.utils.R;
import com.zhz.serviceedu.service.EduSubjectService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

/**
 * <p>
 * 课程科目 前端控制器
 * </p>
 *
 * @author zhz
 * @since 2021-07-03
 */
@RestController
@RequestMapping("/eduservice/subject")
@CrossOrigin
@Api(tags = "课程科目")
public class EduSubjectController {

    @Autowired
    private EduSubjectService eduSubjectService;

    /**
     * 添加课程分类,获取上传过来的文件,把文件内容读取出来
     */
    @PostMapping("/addSubject")
    @ApiOperation(value = "添加课程分类,获取上传过来的文件,把文件内容读取出来")
    public R addSubject(MultipartFile file){
        //上传过来的excel文件
        eduSubjectService.saveSubject(file,eduSubjectService);
        return R.ok();
    }
}

3.3、interface

package com.zhz.serviceedu.service;

import com.zhz.serviceedu.entity.EduSubject;
import com.baomidou.mybatisplus.extension.service.IService;
import org.springframework.web.multipart.MultipartFile;

/**
 * <p>
 * 课程科目 服务类
 * </p>
 *
 * @author zhz
 * @since 2021-07-03
 */
public interface EduSubjectService extends IService<EduSubject> {

    /**
     * 添加课程信息
     *
     * @author zhz
     * @date 2021/07/02 02:18
     * @param file 文件对象,用于获取excel文件
     * @param eduSubjectService 方便监听器部分引用
     */
    void saveSubject(MultipartFile file, EduSubjectService eduSubjectService);
}

3.4、impl

package com.zhz.serviceedu.service.impl;

import com.alibaba.excel.EasyExcel;
import com.zhz.serviceedu.entity.EduSubject;
import com.zhz.serviceedu.entity.excel.SubjectData;
import com.zhz.serviceedu.listener.SubjectExcelListener;
import com.zhz.serviceedu.mapper.EduSubjectMapper;
import com.zhz.serviceedu.service.EduSubjectService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;

/**
 * <p>
 * 课程科目 服务实现类
 * </p>
 *
 * @author zhz
 * @since 2021-07-03
 */
@Service
public class EduSubjectServiceImpl extends ServiceImpl<EduSubjectMapper, EduSubject> implements EduSubjectService {

    /**
     * 添加课程信息
     *
     * @param file 文件对象,用于获取excel文件
     * @param eduSubjectService
     * @author zhz
     * @date 2021/07/02 02:18
     */
    @Override
    public void saveSubject(MultipartFile file, EduSubjectService eduSubjectService) {
        try {
            //文件输入流
            InputStream in = file.getInputStream();
            //调用方法进行读取
            EasyExcel.read(in, SubjectData.class,new SubjectExcelListener(eduSubjectService)).sheet().doRead();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

3.5、listener

package com.zhz.serviceedu.listener;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zhz.servicebase.execptionhandler.GuliException;
import com.zhz.serviceedu.entity.EduSubject;
import com.zhz.serviceedu.entity.excel.SubjectData;
import com.zhz.serviceedu.service.EduSubjectService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

/**
 * @author zhouhengzhe
 * @Description: excel监听器
 * @date 2021/7/3上午2:28
 */
@Slf4j
public class SubjectExcelListener extends AnalysisEventListener<SubjectData> {

    /**
     * 创建有参数构造,传递subjectService用于操作数据库
     * 因为SubjectExcelListener不能交给spring去管理,所以需要自己new,不能注入对象
     * 此处一定要是public,不然永远获取不到对象
     */
    public EduSubjectService eduSubjectService;
    public SubjectExcelListener() {
    }
    public SubjectExcelListener(EduSubjectService eduSubjectService) {
        this.eduSubjectService = eduSubjectService;
    }

    /**
     * 读取excel内容,一行一行进行读取,此处全是业务处理
     * @param subjectData
     * @param analysisContext
     */
    @Override
    public void invoke(SubjectData subjectData, AnalysisContext analysisContext) {
        log.info("进入方法调用");
        if (StringUtils.isEmpty(subjectData)){
            throw new GuliException(20001,"文件数据为空");
        }
        //一行一行去读取excel内容,每次读取有两个值,第一个值为一级分类,第二个值为二级分类
        //判断一级分类是否重复
        EduSubject existOneSubject = this.existOneSubject(eduSubjectService, subjectData.getOneSubjectName());
        if (StringUtils.isEmpty(existOneSubject)){
            existOneSubject=new EduSubject();
            existOneSubject.setParentId("0");
            //一级分类名称
            existOneSubject.setTitle(subjectData.getOneSubjectName());
            eduSubjectService.save(existOneSubject);
        }
        //获取一级分类的pid值
        String pid=existOneSubject.getId();
        //添加二级分类
        // 判断二级分类是否重复
        EduSubject existTwoSubject = this.existTwoSubject(eduSubjectService, subjectData.getTwoSubjectName(), pid);
        if (StringUtils.isEmpty(existTwoSubject)){
            existTwoSubject=new EduSubject();
            existTwoSubject.setParentId(pid);
            //二级分类名称
            existTwoSubject.setTitle(subjectData.getTwoSubjectName());
            eduSubjectService.save(existTwoSubject);
        }

    }

    /**
     * 读取完成后执行
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {

    }

    /**
     * 判断一级分类是否重复
     * 因为课程的的parent_id为0时,代表是一级分类,并且一级分类数据不重复
     * @param eduSubjectService
     * @param name
     * @return
     */
    private EduSubject existOneSubject(EduSubjectService eduSubjectService,String name){
        QueryWrapper<EduSubject> wrapper=new QueryWrapper<>();
        wrapper.eq("title",name);
        wrapper.eq("parent_id","0");
        EduSubject subject = eduSubjectService.getOne(wrapper);
        return subject;
    }
    /**
     * 判断二级分类是否重复
     *
     * @param eduSubjectService
     * @param name
     * @param pid
     * @return
     */
    private EduSubject existTwoSubject(EduSubjectService eduSubjectService,String name,String pid){
        QueryWrapper<EduSubject> wrapper=new QueryWrapper<>();
        wrapper.eq("title",name);
        wrapper.eq("parent_id",pid);
        EduSubject eduSubject = eduSubjectService.getOne(wrapper);
        return eduSubject;
    }
}

3.6、小细节,实体类pojo

因为mybatisplus生成的实体类的主键生成策略是IdType.ID_WORKER,所以需要修改成IdType.ID_WORKER_STR,否则会有转换问题

package com.zhz.serviceedu.entity;

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import java.util.Date;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;

/**
 * <p>
 * 课程科目
 * </p>
 *
 * @author zhz
 * @since 2021-07-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;

}

3.7、其余,swagger集成,R类统一返回,统一日志等,请看我其他博客

统一日志:https://blog.csdn.net/zhouhengzhe/article/details/118078080
统一返回值:https://blog.csdn.net/zhouhengzhe/article/details/118065066
统一异常:https://blog.csdn.net/zhouhengzhe/article/details/118064739
swagger集成:https://blog.csdn.net/zhouhengzhe/article/details/118063779

到此这篇关于SpringBoot集成EasyExcel的应用场景的文章就介绍到这了,更多相关SpringBoot集成EasyExcel内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • SpringBoot中EasyExcel实现Excel文件的导入导出

    前言 在我们日常的开发过程中经常会使用Excel文件的形式来批量地上传下载系统数据,我们最常用的工具是Apache poi,但是如果数据到底上百万时,将会造成内存溢出的问题,那么我们怎么去实现百万数据批量导入导出. 正文 Easyexcel Easyexcel 是阿里巴巴的开源项目,用来优化Excel文件处理过程: poi消耗内存严重:Java解析.生成Excel比较有名的框架有Apache poi.jxl.但他们都存在一个严重的问题就是非常的耗内存,poi有一套SAX模式的API可以一定程度的

  • SpringBoot集成EasyExcel实现Excel导入的方法

    第一次正式的写文章进行分享,如果文章中有什么问题,欢迎大家在文末的群内反馈. 一.背景 为什么会用Easyexcel来做Excel上传 平时项目中经常使用EasyExcel从本地读取Excel中的数据,还有一个前端页面对需要处理的数据进行一些配置(如:Excel所在的文件夹,Excel的文件名,以及Sheet列名.处理数据需要的某些参数),由于每次都是读取的本地的文件,我就在想,如果某一天需要通过前端上传excel给我,让我来进行处理我又应该怎么办呢?我怎么才能在尽量少修改代码的前提下实现这个功

  • SpringBoot整合EasyExcel实现文件导入导出

    准备工作 注意:点击查看官网Demo 1. 引入pom依赖 <!--easyExcel--> <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> </dependency> 2. 实现功能 结合Vue前端,实现浏览器页面直接导出日志文件 实现文件的导入 Excel文件下载 3. 日志实体类 实体类里有自定义转换器:用于

  • SpringBoot集成EasyExcel的步骤

    目录 一 .EasyExcel简介 三.依赖 四.监听 五.接口导入Excel 六.接口 导出Excel (HttpServletResponse response, HttpServletRequest request) 七.本地导入.本地导出 一 .EasyExcel简介 EasyExcel优势    注解式自定义操作.    输入输出简单,提供输入输出过程的接口    支持一定程度的单元格合并等灵活化操作 二.常用注解 @ExcelProperty 指定当前字段对应excel中的那一列.可

  • SpringBoot集成EasyExcel的应用场景分析

    1.介绍 官网地址:https://www.yuque.com/easyexcel 特点: 1.Java领域解析.生成Excel比较有名的框架有Apache poi.jxl等.但他们都存在一个严重的问题就是 非常的耗内存.如果你的系统并发量不大的话可能还行,但是一旦并发上来后一定会OOM或 者JVM频繁的full gc. 2.EasyExcel是阿里巴巴开源的一个excel处理框架,以使用简单.节省内存著称.EasyExcel能大大减 少占用内存的主要原因是在解析Excel时没有将文件数据一次性

  • Springboot集成ClickHouse及应用场景分析

    ClickHouse应用场景: 1.绝大多数请求都是用于读访问的2.数据需要以大批次(大于1000行)进行更新,而不是单行更新:或者根本没有更新操作3.数据只是添加到数据库,没有必要修改4.读取数据时,会从数据库中提取出大量的行,但只用到一小部分列5.表很“宽”,即表中包含大量的列6.查询频率相对较低(通常每台服务器每秒查询数百次或更少)7.对于简单查询,允许大约50毫秒的延迟8.列的值是比较小的数值和短字符串(例如,每个URL只有60个字节)9.在处理单个查询时需要高吞吐量(每台服务器每秒高达

  • SpringBoot集成Redisson实现延迟队列的场景分析

    使用场景 1.下单成功,30分钟未支付.支付超时,自动取消订单 2.订单签收,签收后7天未进行评价.订单超时未评价,系统默认好评 3.下单成功,商家5分钟未接单,订单取消 4.配送超时,推送短信提醒 ...... 对于延时比较长的场景.实时性不高的场景,我们可以采用任务调度的方式定时轮询处理.如:xxl-job 今天我们采用一种比较简单.轻量级的方式,使用 Redis 的延迟队列来进行处理.当然有更好的解决方案,可根据公司的技术选型和业务体系选择最优方案.如:使用消息中间件Kafka.Rabbi

  • Springboot集成第三方jar快速实现微信、支付宝等支付场景

    前言 最近有个小型的活动外包项目,要集成一下支付功能,因为项目较小,按照微信官方文档的配置开发又极容易出错,加上个人又比较懒. 于是在gitee上找到一个封装好的各种支付场景业务,只需要自己将支付参数修改一下就能成功调起支付业务,实现真正的快速开发. 一.项目地址 官方网站:https://javen205.gitee.io/ijpay/ Gitee仓库: https://gitee.com/javen205/IJPay 官方示例程序源码:https://gitee.com/javen205/I

  • SpringBoot 过滤器、拦截器、监听器对比及使用场景分析

    一.关系图理解 二.区别 1.过滤器 过滤器是在web应用启动的时候初始化一次, 在web应用停止的时候销毁 可以对请求的URL进行过滤, 对敏感词过滤 挡在拦截器的外层 实现的是 javax.servlet.Filter 接口 ,是 Servlet 规范的一部分 在请求进入容器后,但在进入servlet之前进行预处理,请求结束是在servlet处理完以后 依赖Web容器 会多次执行 过滤器简介 过滤器的英文名称为 Filter, 是 Servlet 技术中最实用的技术.如同它的名字一样,过滤器

  • SpringBoot集成Mybatis-Plus多租户架构实现

    目录 一. 什么是多租户 二. 多租户架构以及数据隔离方案 1. 独立数据库 2. 共享数据库,独立 Schema 3. 共享数据库,共享 Schema,共享数据表 三.多租户架构适用场景? 四. 技术实现 正式进入主题 1. 创建Spring Boot项目 2. 单元测试 目前公司产品就是对外企业服务,入职后了解到SaaS模式和私有部署,当我第一次听到SaaS时,我不是很理解.经过查阅资料,以及在后续研发功能时,不断的加深了对多租户的理解. 那么接下来让我们问自己几个问题: 1.什么是多租户架

  • Springboot集成RabbitMQ死信队列的实现

    目录 关于死信队列 什么样的消息会进入死信队列? 场景分析 代码实现 场景模拟 生产者 消费者,设置死信队列监听 关于死信队列 在大多数的MQ中间件中,都有死信队列的概念.死信队列同其他的队列一样都是普通的队列.在RabbitMQ中并没有特定的"死信队列"类型,而是通过配置,将其实现. 当我们在创建一个业务的交换机和队列的时候,可以配置参数,指明另一个队列为当前队列的死信队列,在RabbitMQ中,死信队列(严格的说应该是死信交换机)被称为DLX Exchange.当消息"死

  • SpringBoot集成Mybatis并测试

    目录 1.SpringBoot链接druid连接池 2.SpringBoot集成Mybatis 2.1.引入Mybatis-generator 2.2.集成mybatis并测试 3.其它 3.1.自定义druid链接池 3.2.SpringBoot的Mybatis其它配置 首先我们先新建一个项目,需要选择以下依赖: 1.SpringBoot链接druid连接池 1.在pom文件中加入druid连接池场景启动器,如下所示: <!-- druid 场景启动器 --> <dependency&

随机推荐