EasyExcel 动态列映射读取常见异常处理与解决方案
1. 列名不匹配异常
现象:读取时抛出 ExcelAnalysisException,提示 "Can not find header"
原因:动态列名与Java对象字段注解不匹配
解决方案:
public class DynamicData {
@ExcelProperty("动态列_*") // 通配符匹配列名前缀
private Map<String, String> dynamicColumns;
}
处理逻辑:
- 使用
@ExcelProperty注解配合通配符* - 通过
Map接收动态列数据 - 确保Excel列名符合正则匹配规则
2. 数据类型转换异常
现象:数字/日期格式解析失败,抛出 DataConvertException
原因:Excel数据类型与Java字段类型不兼容
解决方案:
public class CustomConverter implements Converter<LocalDateTime> {
@Override
public LocalDateTime convert(String value) {
return LocalDateTime.parse(value, DateTimeFormatter.ISO_DATE);
}
}
@ExcelProperty(value = "日期列", converter = CustomConverter.class)
private LocalDateTime dateColumn;
处理要点:
- 实现
Converter接口自定义转换逻辑 - 处理空值:
if(value == null) return null; - 添加格式校验:
try-catch捕获格式异常
3. 动态列缺失异常
现象:部分动态列未读取到数据
原因:列位置变化导致映射失效
解决方案:
ReadSheet readSheet = EasyExcel.readSheet()
.headRowNumber(2) // 设置表头行
.registerReadListener(new AnalysisEventListener() {
@Override
public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
// 动态获取列索引
columnIndex = headMap.entrySet().stream()
.filter(e -> e.getValue().contains("动态列"))
.findFirst()
.map(Map.Entry::getKey);
}
});
优化策略:
- 使用
headMap动态获取列索引 - 添加默认值逻辑:
columnIndex.orElse(0)
4. 大数据量内存溢出
现象:读取大文件时 OutOfMemoryError
原因:默认全量加载数据到内存
解决方案:
// 分页读取配置
ReadSheet readSheet = EasyExcel.readSheet()
.head(DynamicData.class)
.registerReadListener(new PageReadListener(dataList -> {
processBatch(dataList); // 分批处理
dataList.clear(); // 清空缓存
}, 1000)); // 每1000行处理一次
关键参数:
PageReadListener分批处理数据- 设置JVM参数:
-Xms512m -Xmx2g - 使用
SXSSFWorkbook模式
5. 多级表头解析异常
现象:复杂表头数据映射错误
解决方案:
@ExcelProperty({"主标题", "子标题"}) // 多级表头声明
private String nestedColumn;
// 读取配置
EasyExcel.read(file)
.extraRead(CacheExtra.class) // 启用缓存
.headRowNumber(3) // 表头占3行
.doRead();
处理技巧:
- 使用数组声明多级表头:
@ExcelProperty({"一级", "二级"}) - 调整
headRowNumber匹配实际表头行数 - 通过
@ExcelIgnoreUnannotated忽略未注解字段
综合处理方案
public class DynamicReadHandler {
public void readExcel(MultipartFile file) {
EasyExcel.read(file.getInputStream())
.registerConverter(new CustomConverter()) // 注册转换器
.registerReadListener(new DynamicHeadListener()) // 动态列处理器
.head(DynamicData.class)
.sheet()
.doRead();
}
private static class DynamicHeadListener extends AnalysisEventListener<DynamicData> {
private final Map<String, Integer> columnIndexMap = new HashMap<>();
@Override
public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
headMap.forEach((index, name) ->
columnIndexMap.put(name, index));
}
@Override
public void invoke(DynamicData data, AnalysisContext context) {
// 动态处理列数据
Integer index = columnIndexMap.get("动态列");
if(index != null) {
data.setDynamicValue(context.readRowHolder().getCell(index));
}
}
}
}
最佳实践:
- 使用
@ExcelIgnore忽略不需要的列 - 添加异常重试机制:
try {
excelReader.read();
} catch (ExcelAnalysisException e) {
log.error("解析失败行: {}", e.getRowIndex());
// 跳过错误行继续读取
context.readRowHolder().next();
}
- 通过
ReadCellData获取原始数据:
ReadCellData<?> cellData = context.readRowHolder().getCell(0);
Object value = cellData.getData(); // 原始值
CellDataTypeEnum type = cellData.getType(); // 数据类型
12万+

被折叠的 条评论
为什么被折叠?



