決議excel我們常用的應該就是poi了,這個比較坑,之前專案用過一下,這次我們使用一下阿里的easyexcel吧!easyexcel的使用很簡單,比較類似于最開始決議xml使用的SAX,就是每讀取檔案一行,就直接進行處理,完全不需要檔案都加載到記憶體中!!!
easyexcel的官方檔案
1. 隨意新建一個springboot專案,匯入常見的依賴(基于springboot+mybatis+mybatisplus+lombok+swagger),然后再匯入easyexcel:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.1.1</version>
</dependency>
2. excel檔案中的內容,比如淘寶商品的分類,肯定是分為一級,二級,三級分類等等,下圖所示,一個一級分類對應多個二級分類,一個二級對應多個三級,等等

我們就不弄那么麻煩了,以一個課程的分類為例,有一級分類二級分類,下圖的excel檔案所示,我們需要將這個excel檔案上傳,然后通過easyexcel決議出來,丟到資料庫中,類似圖中資料庫表中的資料

sql腳本如下::
create table subject ( id char(19) not null comment '課程類別ID' primary key, title varchar(10) not null comment '類別名稱', parent_id char(19) default '0' not null comment '父ID' )comment '課程科目'; create index idx_parent_id on subject (parent_id);
3. controller代碼:
package com.protagonist.edu.controller; import com.protagonist.edu.service.SubjectService; import com.protagonist.responseVO.Result; import com.protagonist.responseVO.StatusCode; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; 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; import javax.annotation.Resource; /** * <p> * 課程科目 前端控制器 * </p> * * @author protagonist * @since 2020-10-01 */ @Api("課程分類的api") @RestController @RequestMapping("/edu/subject") @Slf4j public class SubjectController { @Resource private SubjectService subjectServiceImpl; //添加課程分類,上傳excel然后進行讀取,決議成物件 @PostMapping("/addSubject") @ApiOperation(value = "上傳excel檔案中的一級分類和二級分類") public Result addSubject(MultipartFile file) { subjectServiceImpl.saveSubject(file); return new Result<>(true, StatusCode.OK, "添加課程分類成功"); } }
4.service和serviceImpl:
public interface SubjectService extends IService<Subject> { /** * 添加課程分類 * @param file */ void saveSubject(MultipartFile file); } @Service @Slf4j public class SubjectServiceImpl extends ServiceImpl<SubjectMapper, Subject> implements SubjectService { @Override public void saveSubject(MultipartFile file) { try{ InputStream inputStream = file.getInputStream(); //讀取excel EasyExcel.read(inputStream, ExcelSubjectData.class,new SubjectExcelListener(this)).sheet().doRead(); }catch (Exception e){ log.error("讀取excel檔案例外",e); throw new ProtagonistException(StatusCode.READ_FILE_ERROR,"讀取excel檔案例外"); } } }
5.entity
@Data @EqualsAndHashCode(callSuper = false) @Accessors(chain = true) @TableName("subject") @ApiModel(value="Subject物件", description="課程科目") public class Subject 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; }
6.我們還需要一個類,這個類的每一個實體都對應excel中每一行資料,我們將每一行資料都轉成一個物件之后,然后進行處理就方便了;
package com.protagonist.edu.excel; import com.alibaba.excel.annotation.ExcelProperty; import lombok.Data; @Data public class ExcelSubjectData { /** * 一級分類 */ @ExcelProperty(index = 0) private String oneSubjectName; /** * 二級分類 */ @ExcelProperty(index = 1) private String twoSubjectName; }
7.listener,之前說過easyexcel是每讀一行資料都會處理一下, 所以這里需要來一個監聽器:
package com.protagonist.edu.entity.listener; import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.event.AnalysisEventListener; import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.protagonist.edu.entity.Subject; import com.protagonist.edu.excel.ExcelSubjectData; import com.protagonist.edu.service.SubjectService; import com.protagonist.responseVO.StatusCode; import com.protagonist.servicebase.exception.ProtagonistException; import lombok.extern.slf4j.Slf4j; import java.util.Objects; @Slf4j public class SubjectExcelListener extends AnalysisEventListener<ExcelSubjectData> { //這里必須來個構造器,將service傳過來,然后再監聽器中每處理一行就可以直接進行入庫操作; //其實可以使用mybatis的批量入庫的 private SubjectService subjectService; public SubjectExcelListener(SubjectService subjectService){ this.subjectService = subjectService; } //這個方法讀取excel內容,一行一行讀取,每一行都會觸發這個方法,而excelSubjectData表示的就是excel中的一行資料 //注意這里的第一行不會讀,默認是表頭 @Override public void invoke(ExcelSubjectData excelSubjectData, AnalysisContext analysisContext) { log.info("每一行處理excel資料============================="); if (Objects.isNull(excelSubjectData)){ throw new ProtagonistException(StatusCode.ERROR,"檔案內容為空"); } //獲取每一行中的第一個資料和第二個資料,然后判斷資料庫中是否有該分類資訊,沒有的話才會插入資料庫 String oneSubjectName = excelSubjectData.getOneSubjectName(); String twoSubjectName = excelSubjectData.getTwoSubjectName(); //判斷資料庫中有沒有一級分類,沒有的話就插入一級分類 Subject oneSubject = getOneOrTwoSubject(subjectService, oneSubjectName, "0"); if (Objects.isNull(oneSubject)){ oneSubject = new Subject(); oneSubject.setTitle(oneSubjectName); oneSubject.setParentId("0"); subjectService.save(oneSubject); } log.info("資料入庫之后:{}", JSON.toJSONString(oneSubject)); //判斷資料庫中有沒有二級分類,要判斷這個二級分類的話必須先獲取此時的父id,這里有個很神奇的地方,mybatisplus在執行save(T obj)方法完成之后, // 就會將生成的主鍵賦值給obj中 //oneSubject.getId()可以獲取當前二級分類對應的一級分類的id Subject twoSubject = getOneOrTwoSubject(subjectService, twoSubjectName, oneSubject.getId()); if (Objects.isNull(twoSubject)){ twoSubject = new Subject(); twoSubject.setParentId(oneSubject.getId()); twoSubject.setTitle(twoSubjectName); subjectService.save(twoSubject); } } /** * 根據課程名稱和父id查詢課程分類表中的資料 * @param subjectService * @param name * @param pid * @return */ private Subject getOneOrTwoSubject(SubjectService subjectService,String name,String pid){ QueryWrapper<Subject> queryWrapper = new QueryWrapper<>(); queryWrapper.eq("title",name); queryWrapper.eq("parent_id",pid); return subjectService.getOne(queryWrapper); } @Override public void doAfterAllAnalysed(AnalysisContext analysisContext) { } }
8.測驗成功


轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/152082.html
標籤:其他
