SpringBoot集成EasyExcel的應(yīng)用場景分析
1、介紹
官網(wǎng)地址:https://www.yuque.com/easyexcel
特點:
1、Java領(lǐng)域解析、生成Excel比較有名的框架有Apache poi、jxl等。但他們都存在一個嚴重的問題就是 非常的耗內(nèi)存。如果你的系統(tǒng)并發(fā)量不大的話可能還行,但是一旦并發(fā)上來后一定會OOM或 者JVM頻繁的full gc。
2、EasyExcel是阿里巴巴開源的一個excel處理框架,以使用簡單、節(jié)省內(nèi)存著稱。EasyExcel能大大減 少占用內(nèi)存的主要原因是在解析Excel時沒有將文件數(shù)據(jù)一次性全部加載到內(nèi)存中,而是從磁盤上一 行行讀取數(shù)據(jù),逐個解析。
3、EasyExcel采用一行一行的解析模式,并將一行的解析結(jié)果以觀察者的模式通知處理 (AnalysisEventListener)。
2、應(yīng)用場景
1、數(shù)據(jù)導(dǎo)入:減輕錄入工作量
2、數(shù)據(jù)導(dǎo)出:統(tǒng)計信息歸檔
3、數(shù)據(jù)傳輸:異構(gòu)系統(tǒng)之間數(shù)據(jù)傳輸
3、要實現(xiàn)的效果
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 '創(chuàng)建時間', `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='課程科目';

轉(zhuǎn)成->

3、使用
3.1、pom依賴導(dǎo)入
溫馨提示:以下版本不能更換,換了可能會不行
<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;
/**
* 添加課程分類,獲取上傳過來的文件,把文件內(nèi)容讀取出來
*/
@PostMapping("/addSubject")
@ApiOperation(value = "添加課程分類,獲取上傳過來的文件,把文件內(nèi)容讀取出來")
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>
* 課程科目 服務(wù)類
* </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 方便監(jiān)聽器部分引用
*/
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>
* 課程科目 服務(wù)實現(xiàn)類
* </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();
//調(diào)用方法進行讀取
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監(jiān)聽器
* @date 2021/7/3上午2:28
*/
@Slf4j
public class SubjectExcelListener extends AnalysisEventListener<SubjectData> {
/**
* 創(chuàng)建有參數(shù)構(gòu)造,傳遞subjectService用于操作數(shù)據(jù)庫
* 因為SubjectExcelListener不能交給spring去管理,所以需要自己new,不能注入對象
* 此處一定要是public,不然永遠獲取不到對象
*/
public EduSubjectService eduSubjectService;
public SubjectExcelListener() {
}
public SubjectExcelListener(EduSubjectService eduSubjectService) {
this.eduSubjectService = eduSubjectService;
}
/**
* 讀取excel內(nèi)容,一行一行進行讀取,此處全是業(yè)務(wù)處理
* @param subjectData
* @param analysisContext
*/
@Override
public void invoke(SubjectData subjectData, AnalysisContext analysisContext) {
log.info("進入方法調(diào)用");
if (StringUtils.isEmpty(subjectData)){
throw new GuliException(20001,"文件數(shù)據(jù)為空");
}
//一行一行去讀取excel內(nèi)容,每次讀取有兩個值,第一個值為一級分類,第二個值為二級分類
//判斷一級分類是否重復(fù)
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();
//添加二級分類
// 判斷二級分類是否重復(fù)
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);
}
}
/**
* 讀取完成后執(zhí)行
*/
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
}
/**
* 判斷一級分類是否重復(fù)
* 因為課程的的parent_id為0時,代表是一級分類,并且一級分類數(shù)據(jù)不重復(fù)
* @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;
}
/**
* 判斷二級分類是否重復(fù)
*
* @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、小細節(jié),實體類pojo
因為mybatisplus生成的實體類的主鍵生成策略是IdType.ID_WORKER,所以需要修改成IdType.ID_WORKER_STR,否則會有轉(zhuǎn)換問題
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 = "創(chuàng)建時間")
@TableField(fill = FieldFill.INSERT)
private Date gmtCreate;
@ApiModelProperty(value = "更新時間")
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date gmtModified;
}
3.7、其余,swagger集成,R類統(tǒng)一返回,統(tǒng)一日志等,請看我其他博客
統(tǒng)一日志:https://blog.csdn.net/zhouhengzhe/article/details/118078080
統(tǒng)一返回值:https://blog.csdn.net/zhouhengzhe/article/details/118065066
統(tǒng)一異常:https://blog.csdn.net/zhouhengzhe/article/details/118064739
swagger集成:https://blog.csdn.net/zhouhengzhe/article/details/118063779
到此這篇關(guān)于SpringBoot集成EasyExcel的應(yīng)用場景的文章就介紹到這了,更多相關(guān)SpringBoot集成EasyExcel內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot Maven打包失敗報:class lombok.javac.apt.Lombo
最新項目部署的時候,出現(xiàn)了一個maven打包失敗的問題,報:class lombok.javac.apt.LombokProcessor錯誤,所以本文給大家介紹了如何解決SpringBoot Maven 打包失?。篶lass lombok.javac.apt.LombokProcessor 錯誤,需要的朋友可以參考下2023-12-12
SpringBoot中Mybatis + Druid 數(shù)據(jù)訪問的詳細過程
Spring Boot 底層都是采用 SpringData 的方式進行統(tǒng)一處理各種數(shù)據(jù)庫,SpringData也是Spring中與SpringBoot、SpringCloud 等齊名的知名項目,下面看下SpringBoot Mybatis Druid數(shù)據(jù)訪問的詳細過程,感興趣的朋友一起看看吧2021-11-11
MyBatisPlus中使用or()和and()遇到的問題及細節(jié)處理
這篇文章主要介紹了MyBatisPlus中使用or()和and()遇到的問題,本文通過多種寫法實例代碼相結(jié)合給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-08-08
Spring Security使用中Preflight請求和跨域問題詳解
這篇文章主要給大家介紹了關(guān)于Spring Security使用中Preflight請求和跨域問題的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2017-11-11

