目录
- 🍑一、背景
- 🍑二、开发验证
- 🍊2.1、引入easyexcel依赖
- 🍊2.2、创建表及基础代码
- 🍊2.3、处理类及接口
- 🍓2.3.1、EasyExcel监听处理器
- 🍓2.3.2、Controller接口
- 🍓2.3.3、service调用监听器
- 🍊2.4、启动项目,通过swagger接口测试
- 🍓2.4.1、上传excel
- 🍓2.4.2、excel详情
- 🍓2.4.3、查看数据库验证
- 🍑三、其它
🔼上一集:小钊记
🍑一、背景
大概2023年7月6号,整了一个180天倒计时(距离2024元旦),设定了一些计划,通过腾讯在线文档记录每天完成情况。突然想起来,今年五一的时候,搭建了一个系统,就是上面的小钊记,想着要不把180天倒计时计划表导入数据库,之前也做过解析excel,是通过poi,springboot 解析Excel(栏位与实体类一一对应),这次改用Easy Excel
试一下,听名字就感觉比较简单。
🍑二、开发验证
🍊2.1、引入easyexcel依赖
<dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.1.1</version>
</dependency>
🍊2.2、创建表及基础代码
- 日常记录表
DROP TABLE IF EXISTS `t_rxz_daily_record`; create table t_rxz_daily_record (id int not null auto_increment comment '主键',record_date Date not null comment '记录日期',wake_up_time time not null comment '起床时间',lunch_break_duration varchar(50) not null comment '午休时长',hunger_before_bedtime varchar(50) not null comment '睡前饿意',motion varchar(50) not null comment '运动',learning varchar(50) not null comment '学习',sleep_time varchar(50) not null comment '睡觉时间',explosive_red_rate varchar(50) not null comment '爆红率',net_weight FLOAT not null comment '净重',update_time datetime default CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP comment '更新时间',primary key (id) );
- 基础代码
-
entity
package com.renxiaozhao.bean.entity;import java.io.Serializable; import java.sql.Time; import java.util.Date;import com.baomidou.mybatisplus.annotation.TableName;import io.swagger.annotations.ApiModelProperty; import lombok.Data;/*** 日常记录表实体.* @author : 韧小钊* @date : 2023-8-10*/ @Data @TableName("t_rxz_daily_record") public class DailyRecordEntity implements Serializable {private static final long serialVersionUID = 5252694875850308782L;/** 主键 */@ApiModelProperty(name = "主键",notes = "")private Integer id ;/** 记录日期 */@ApiModelProperty(name = "记录日期",notes = "")private Date recordDate ;/** 起床时间 */@ApiModelProperty(name = "起床时间",notes = "")private Time wakeUpTime ;/** 午休时长 */@ApiModelProperty(name = "午休时长",notes = "")private String lunchBreakDuration ;/** 睡前饿意 */@ApiModelProperty(name = "睡前饿意",notes = "")private String hungerBeforeBedtime ;/** 运动 */@ApiModelProperty(name = "运动",notes = "")private String motion ;/** 学习 */@ApiModelProperty(name = "学习",notes = "")private String learning ;/** 睡觉时间 */@ApiModelProperty(name = "睡觉时间",notes = "")private String sleepTime ;/** 爆红率 */@ApiModelProperty(name = "爆红率",notes = "")private String explosiveRedRate ;/** 净重 */@ApiModelProperty(name = "净重",notes = "")private Float netWeight ;/** 更新时间 */@ApiModelProperty(name = "更新时间",notes = "")private Date updateTime ;}
-
mapper
package com.renxiaozhao.dao.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.renxiaozhao.bean.entity.DailyRecordEntity;public interface DailyRecordMapper extends BaseMapper<DailyRecordEntity>{}
-
service接口及实现类
package com.renxiaozhao.service.impl;import org.springframework.stereotype.Service;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.renxiaozhao.bean.entity.DailyRecordEntity; import com.renxiaozhao.dao.mapper.DailyRecordMapper; import com.renxiaozhao.service.inf.DailyRecordService;@Service public class DailyRecordServiceImpl extends ServiceImpl<DailyRecordMapper, DailyRecordEntity> implements DailyRecordService {}
package com.renxiaozhao.service.inf;import com.baomidou.mybatisplus.extension.service.IService; import com.renxiaozhao.bean.entity.DailyRecordEntity;public interface DailyRecordService extends IService<DailyRecordEntity> {}
-
🍊2.3、处理类及接口
🍓2.3.1、EasyExcel监听处理器
- 读取监听器(ReadListener): 在读取 Excel 文件之前,可以使用
BeforeReadListener
接口来处理读取开始前的事件。在每次读取一行数据时,可以使用ReadListener
接口的onRead
方法来处理读取到的数据。在读取完成后,可以使用AfterReadListener
接口来处理读取结束后的事件。 - 写入监听器(WriteListener): 在写入 Excel 文件之前,可以使用
BeforeWriteListener
接口来处理写入开始前的事件。在每次写入一行数据时,可以使用WriteListener
接口的onWrite
方法来处理要写入的数据。在写入完成后,可以使用AfterWriteListener
接口来处理写入结束后的事件。
分析监听器(AnalysisEventListener): - AnalysisEventListener: 是一种用于读取大量数据时的监听器接口。您可以实现
AnalysisEventListener
接口,并在onRead
方法中处理读取到的每一行数据。EasyExcel 会将读取的数据分批处理,以减少内存消耗。
目前只用到了读取监听器,代码如下:
package com.renxiaozhao.service.impl;import java.sql.Time;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import com.renxiaozhao.bean.entity.DailyRecordEntity;
import com.renxiaozhao.service.util.DateUtils;import lombok.extern.slf4j.Slf4j;/*** 初始化表格数据.*/
@Slf4j
public class ExcelListener implements ReadListener<LinkedHashMap<Integer, String>> {List<DailyRecordEntity> dailyRecords = new ArrayList<>();@Overridepublic void invoke(LinkedHashMap<Integer, String> rowData, AnalysisContext context) {DailyRecordEntity record = new DailyRecordEntity();try {// 记录日期record.setRecordDate(DateUtils.parseDate(rowData.get(0)));// 起床时间record.setWakeUpTime(Time.valueOf(rowData.get(1) + ":00"));// 午休时长record.setLunchBreakDuration(rowData.get(2));// 睡前饿意record.setHungerBeforeBedtime(rowData.get(3));// 运动record.setMotion(rowData.get(4));// 学习record.setLearning(rowData.get(5));// 睡觉时间record.setSleepTime(rowData.get(6));// 爆红率record.setExplosiveRedRate(rowData.get(7));// 净重record.setNetWeight(Float.parseFloat(rowData.get(8)));} catch (ParseException e) {log.error(rowData + "参数转化格式失败:",e);}dailyRecords.add(record);}@Overridepublic void doAfterAllAnalysed(AnalysisContext analysisContext) {}public List<DailyRecordEntity> getDailyRecords() {return dailyRecords;}}
🍓2.3.2、Controller接口
@PostMapping("/exportRecord")@ApiOperation(value = "导入每日记录信息", notes = "导入每日记录信息")public Result<String> exportRecord(@RequestParam("file") MultipartFile file) {try {sportRecordService.exportRecord(file);return Result.success();} catch (Exception e) {log.error("导入记录数据异常", e);return Result.error("导入记录数据异常" + e.getMessage());}}
🍓2.3.3、service调用监听器
支持多个sheet
,每遍历完一个记得清空数据,图中listener.getDailyRecords().clear()
是在清空 listener
对象中的 dailyRecords
数据,以便在处理下一个 sheet
时,相关数据不会重叠或占用过多的内存。
@Overridepublic void exportRecord(MultipartFile file) {String message = "共导入%s个月记录,成功%s,失败%s";StringBuilder failMessages = new StringBuilder();InputStream inputStream = null;ExcelReader excelReader = null;try {inputStream = file.getInputStream();ExcelListener listener = new ExcelListener();excelReader = EasyExcel.read(inputStream).registerReadListener(listener).build();//获取sheet页List<ReadSheet> readSheets = excelReader.excelExecutor().sheetList();int success = 0;int fail = 0;for (ReadSheet readSheet : readSheets) {String sheetName = readSheet.getSheetName();//读取excel数据excelReader.read(readSheet);List<DailyRecordEntity> records = listener.getDailyRecords();try {if (records != null && records.size() > 0) {//保存表信息boolean flag = dailyRecordService.saveBatch(records);if (flag) {success++;}}} catch (Exception e) {log.error("插入数据错误", e);failMessages.append("sheet ").append(sheetName).append(":").append(e.getMessage()).append(";");fail++;} finally {listener.getDailyRecords().clear();}}message = String.format(message, success + fail, success, fail);if (!StringUtils.isEmpty(failMessages.toString())) {log.error(failMessages.toString());}} catch (Exception e) {log.error("读取文件失败", e);} finally {if (inputStream != null) {try {inputStream.close();} catch (IOException e) {log.error("读取文件失败", e);}}if (excelReader != null) {excelReader.finish();}}}
🍊2.4、启动项目,通过swagger接口测试
🍓2.4.1、上传excel
🍓2.4.2、excel详情
导出腾讯在线文档,按照月份划分sheet,详情如下:
- 7月
- 8月
🍓2.4.3、查看数据库验证
成功登记了7、8月份的数据
🍑三、其它
确实简单好用!!!