完美解决springboot使用EasyExcel读取excel数据报错:com.alibaba.excel.exception.ExcelAnalysisException: Listen error!
项目背景:springboot 、mybatis-puls
1、起因,在开始使用excel的时候书写监听器,在导入读取的时候出现Listen error!在查了全网之后发现只有一位博主写了有,但是和自己出现的问题还是有点差异【记录所用】,其实是很简单的错误,我硬是搞了很久,气死
2、贴出代码
监听器:
package com.iv.unlock.business.excel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.iv.unlock.business.entity.PlatformUser;
import com.iv.unlock.business.service.IPlatformUserService;
import lombok.extern.slf4j.Slf4j;
import com.alibaba.fastjson.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
@Slf4j
public class PlatformUserListener extends AnalysisEventListener<PlatformUser> {
private static final Logger LOGGER = LoggerFactory.getLogger(PlatformUserListener.class);
/**
* 每隔5条存储数据库,实际使用中可以3000条,然后清理list ,方便内存回收
*/
private static final int BATCH_COUNT = 5;
List<PlatformUser> list = new ArrayList<PlatformUser>();
/**
* 假设这个是一个DAO,当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象没用。
*/
private IPlatformUserService platformUserService;
public PlatformUserListener() {
// 这里是demo,所以随便new一个。实际使用如果到了spring,请使用下面的有参构造函数
}
/**
* 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来
*
* @param platformUserService
*/
public PlatformUserListener(IPlatformUserService platformUserService) {
this.platformUserService = platformUserService;
}
/**
* 这个每一条数据解析都会来调用
*
* @param platformUser
* one row value. Is is same as {@link AnalysisContext#readRowHolder()}
* @param context
*/
@Override
public void invoke(PlatformUser platformUser, AnalysisContext context) {
LOGGER.info("解析到一条数据:{}", JSON.toJSONString(platformUser));
platformUser.setCreateTime(LocalDateTime.now());
list.add(platformUser);
// 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
if (list.size() >= BATCH_COUNT) {
saveData();
// 存储完成清理 list
list.clear();
}
}
/**
* 所有数据解析完成了 都会来调用
*
* @param context
*/
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// 这里也要保存数据,确保最后遗留的数据也存储到数据库
saveData();
LOGGER.info("所有数据解析完成!");
}
/**
* 加上存储数据库
*/
private void saveData() {
LOGGER.info("{}条数据,开始存储数据库!", list.size());
platformUserService.saveBatch(list);
LOGGER.info("存储数据库成功!");
}
}
实体类:
@Data
@EqualsAndHashCode(callSuper = true)
public class PlatformUser extends BaseEntity {
private static final long serialVersionUID = 1L;
/**
* 密码
*/
@ExcelProperty(value = "密码")
private String password;
/**
* 账号
*/
@ExcelProperty(value = "账号")
private String account;
/**
* 创建时间
*/
@ExcelProperty(value = "ExpirationTime", index = 2,converter = LocalDateTimeConverter.class)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+")
private LocalDateTime createTime;
/**
* 创建者
*/
@ExcelProperty(value = "创建者")
private String creator;
/**
* 修改时间
*/
@ExcelIgnore
private LocalDateTime modTime;
/**
* 修改人
*/
@ExcelIgnore
private String modifier;
/**
* 产品id
*/
@ExcelProperty(value = "产品ID")
private Long unlockProductId;
/**
* 当前状态 0-check 1-normal
*/
@ExcelProperty(value = "当前状态")
private Integer curStatus;
}
主要是因为类型转换问题!!!!
一般来说int->string 、int->LocalDateTime就会出现这个错误
但是我一直检查类型发现也没什么问题,一直排查问题
最后最后发现是时间格式书写错误了
/**
* 创建时间
*/
@ExcelProperty(value = "ExpirationTime", index = 2,converter = LocalDateTimeConverter.class)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+")
private LocalDateTime createTime;
就是这个,LocalDateTimeConverter
public class LocalDateTimeConverter implements Converter<LocalDateTime> {
@Override
public Class supportJavaTypeKey() {
return LocalDateTime.class;
}
@Override
public CellDataTypeEnum supportExcelTypeKey() {
return CellDataTypeEnum.STRING;
}
@Override
public LocalDateTime convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration){
return LocalDateTime.parse(cellData.getStringValue(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
}
@Override
public CellData convertToExcelData(LocalDateTime value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
return new CellData(value.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
}
}
转换格式是:yyyy-MM-dd HH:mm:ss
而我导入excel文件写的格式是:
好了,完美解决!!!!!
顺便记录一下,在导出的时候,可以通过
@ColumnWidth():设置导出宽度【实体字段上、实体类上】
@ContentRowHeight():设置导出高度【实体类上】