SpringBoot集成EasyExcel的應(yīng)用場(chǎng)景分析
1、介紹
官網(wǎng)地址:https://www.yuque.com/easyexcel
特點(diǎn):
1、Java領(lǐng)域解析、生成Excel比較有名的框架有Apache poi、jxl等。但他們都存在一個(gè)嚴(yán)重的問(wèn)題就是 非常的耗內(nèi)存。如果你的系統(tǒng)并發(fā)量不大的話可能還行,但是一旦并發(fā)上來(lái)后一定會(huì)OOM或 者JVM頻繁的full gc。
2、EasyExcel是阿里巴巴開源的一個(gè)excel處理框架,以使用簡(jiǎn)單、節(jié)省內(nèi)存著稱。EasyExcel能大大減 少占用內(nèi)存的主要原因是在解析Excel時(shí)沒(méi)有將文件數(shù)據(jù)一次性全部加載到內(nèi)存中,而是從磁盤上一 行行讀取數(shù)據(jù),逐個(gè)解析。
3、EasyExcel采用一行一行的解析模式,并將一行的解析結(jié)果以觀察者的模式通知處理 (AnalysisEventListener)。
2、應(yīng)用場(chǎng)景
1、數(shù)據(jù)導(dǎo)入:減輕錄入工作量
2、數(shù)據(jù)導(dǎo)出:統(tǒng)計(jì)信息歸檔
3、數(shù)據(jù)傳輸:異構(gòu)系統(tǒng)之間數(shù)據(jù)傳輸
3、要實(shí)現(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)建時(shí)間', `gmt_modified` datetime NOT NULL COMMENT '更新時(shí)間', 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)入
溫馨提示:以下版本不能更換,換了可能會(huì)不行
<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; /** * 添加課程分類,獲取上傳過(guò)來(lái)的文件,把文件內(nèi)容讀取出來(lái) */ @PostMapping("/addSubject") @ApiOperation(value = "添加課程分類,獲取上傳過(guò)來(lái)的文件,把文件內(nèi)容讀取出來(lái)") public R addSubject(MultipartFile file){ //上傳過(guò)來(lái)的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 文件對(duì)象,用于獲取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ù)實(shí)現(xiàn)類 * </p> * * @author zhz * @since 2021-07-03 */ @Service public class EduSubjectServiceImpl extends ServiceImpl<EduSubjectMapper, EduSubject> implements EduSubjectService { /** * 添加課程信息 * * @param file 文件對(duì)象,用于獲取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)用方法進(jìn)行讀取 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ù)庫(kù) * 因?yàn)镾ubjectExcelListener不能交給spring去管理,所以需要自己new,不能注入對(duì)象 * 此處一定要是public,不然永遠(yuǎn)獲取不到對(duì)象 */ public EduSubjectService eduSubjectService; public SubjectExcelListener() { } public SubjectExcelListener(EduSubjectService eduSubjectService) { this.eduSubjectService = eduSubjectService; } /** * 讀取excel內(nèi)容,一行一行進(jìn)行讀取,此處全是業(yè)務(wù)處理 * @param subjectData * @param analysisContext */ @Override public void invoke(SubjectData subjectData, AnalysisContext analysisContext) { log.info("進(jìn)入方法調(diào)用"); if (StringUtils.isEmpty(subjectData)){ throw new GuliException(20001,"文件數(shù)據(jù)為空"); } //一行一行去讀取excel內(nèi)容,每次讀取有兩個(gè)值,第一個(gè)值為一級(jí)分類,第二個(gè)值為二級(jí)分類 //判斷一級(jí)分類是否重復(fù) EduSubject existOneSubject = this.existOneSubject(eduSubjectService, subjectData.getOneSubjectName()); if (StringUtils.isEmpty(existOneSubject)){ existOneSubject=new EduSubject(); existOneSubject.setParentId("0"); //一級(jí)分類名稱 existOneSubject.setTitle(subjectData.getOneSubjectName()); eduSubjectService.save(existOneSubject); } //獲取一級(jí)分類的pid值 String pid=existOneSubject.getId(); //添加二級(jí)分類 // 判斷二級(jí)分類是否重復(fù) EduSubject existTwoSubject = this.existTwoSubject(eduSubjectService, subjectData.getTwoSubjectName(), pid); if (StringUtils.isEmpty(existTwoSubject)){ existTwoSubject=new EduSubject(); existTwoSubject.setParentId(pid); //二級(jí)分類名稱 existTwoSubject.setTitle(subjectData.getTwoSubjectName()); eduSubjectService.save(existTwoSubject); } } /** * 讀取完成后執(zhí)行 */ @Override public void doAfterAllAnalysed(AnalysisContext analysisContext) { } /** * 判斷一級(jí)分類是否重復(fù) * 因?yàn)檎n程的的parent_id為0時(shí),代表是一級(jí)分類,并且一級(jí)分類數(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; } /** * 判斷二級(jí)分類是否重復(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、小細(xì)節(jié),實(shí)體類pojo
因?yàn)閙ybatisplus生成的實(shí)體類的主鍵生成策略是IdType.ID_WORKER,所以需要修改成IdType.ID_WORKER_STR,否則會(huì)有轉(zhuǎn)換問(wè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對(duì)象", 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)建時(shí)間") @TableField(fill = FieldFill.INSERT) private Date gmtCreate; @ApiModelProperty(value = "更新時(shí)間") @TableField(fill = FieldFill.INSERT_UPDATE) private Date gmtModified; }
3.7、其余,swagger集成,R類統(tǒng)一返回,統(tǒng)一日志等,請(qǐ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)用場(chǎng)景的文章就介紹到這了,更多相關(guān)SpringBoot集成EasyExcel內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot Maven打包失敗報(bào):class lombok.javac.apt.Lombo
最新項(xiàng)目部署的時(shí)候,出現(xiàn)了一個(gè)maven打包失敗的問(wèn)題,報(bào):class lombok.javac.apt.LombokProcessor錯(cuò)誤,所以本文給大家介紹了如何解決SpringBoot Maven 打包失?。篶lass lombok.javac.apt.LombokProcessor 錯(cuò)誤,需要的朋友可以參考下2023-12-12SpringBoot中Mybatis + Druid 數(shù)據(jù)訪問(wèn)的詳細(xì)過(guò)程
Spring Boot 底層都是采用 SpringData 的方式進(jìn)行統(tǒng)一處理各種數(shù)據(jù)庫(kù),SpringData也是Spring中與SpringBoot、SpringCloud 等齊名的知名項(xiàng)目,下面看下SpringBoot Mybatis Druid數(shù)據(jù)訪問(wèn)的詳細(xì)過(guò)程,感興趣的朋友一起看看吧2021-11-11深入解析java HashMap實(shí)現(xiàn)原理
這篇文章主要介紹了深入解析java HashMap實(shí)現(xiàn)原理的相關(guān)資料,需要的朋友可以參考下2015-09-09MyBatisPlus中使用or()和and()遇到的問(wèn)題及細(xì)節(jié)處理
這篇文章主要介紹了MyBatisPlus中使用or()和and()遇到的問(wèn)題,本文通過(guò)多種寫法實(shí)例代碼相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-08-08Spring Security使用中Preflight請(qǐng)求和跨域問(wèn)題詳解
這篇文章主要給大家介紹了關(guān)于Spring Security使用中Preflight請(qǐng)求和跨域問(wèn)題的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2017-11-11