目录
- 🍑一、背景
- 🍑二、开发验证
- 🍊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<>();
@Override
public 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);
}
@Override
public 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
时,相关数据不会重叠或占用过多的内存。
@Override
public 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月份的数据
🍑三、其它
确实简单好用!!!