如何修改easyexcel(当前版本4.0.3)支持native-image构建

(1) Add MyBeanMap



public class MyBeanMap extends HashMap<String, Object> {
    private Object bean;

    public Object getBean() {
        return bean;
    }

    public void setBean(Object bean) {
        this.bean = bean;
    }

    public Object put0(String key, Object value) {
        return super.put(key, value);
    }

    //更新map,更新bean
    @Override
    public Object put(String key, Object value) {
        Field field = ReflectionUtils.findField(bean.getClass(), key);

        //修改bean
        if (field != null) {
            boolean accessible = field.isAccessible();
            try {
                if (!accessible) {
                    ReflectionUtils.makeAccessible(field);
                }
                ReflectionUtils.setField(field, bean, value);
            } finally {
                if (!accessible) {
                    field.setAccessible(accessible);
                }
            }
        }
        return super.put(key, value);
    }

    public Object get(String key) {
        //bean用法
        return super.get(key);
    }
}

(2) Add MyBeanMapUtils

import org.springframework.util.ReflectionUtils;

public class MyBeanMapUtils {
    public static MyBeanMap create(Object bean) {
        MyBeanMap map = new MyBeanMap();
        map.setBean(bean);
        //1.首次初始化map
        ReflectionUtils.doWithFields(bean.getClass(), field -> {
            field.setAccessible(true);
            Object value = ReflectionUtils.getField(field, bean);
            if (value != null) {
                map.put0(field.getName(), value);
            }
        });
        return map;
    }
}

(2) Add reference:

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
        </dependency>

(3) Modify code:
BeanMap dataMap = BeanMapUtils.create(resultModel);
For:

MyBeanMap dataMap=MyBeanMapUtils.create(resultModel);
<think>我们正在解决EasyExcel 4.0.3版本中数据无法正确映射到实体类的问题。根据引用[2]的提示,EasyExcel 3+版本需要特别注意POI依赖的版本,但用户使用的是4.0.3版本,同样可能存在类似问题。此外,数据映射失败可能有多种原因,我们将逐步分析并提供解决方案。 ## 问题分析:数据映射失败的常见原因 1. **实体类字段与Excel列未正确匹配** - 字段名不匹配:Excel表头与实体类字段名不一致。 - 字段类型不匹配:Excel单元格数据类型与实体类字段类型不兼容。 2. **注解配置问题** - 未使用`@ExcelProperty`注解指定映射关系。 - `@ExcelProperty`的`index`属性与列顺序不一致。 3. **依赖冲突** - 如引用[2]所述,EasyExcel 4.0.3依赖的POI版本可能与其他库冲突,导致解析异常。 4. **数据格式问题** - Excel中存在空行或特殊格式(如合并单元格),导致解析中断。 5. **自定义转换器(Converter)问题** - 自定义转换器未正确实现,导致数据转换失败。 ## 解决方案 ### 步骤1:检查实体类注解配置 确保实体类每个字段都使用`@ExcelProperty`注解,并明确指定列名或列索引(从0开始)。例如: ```java public class User { @ExcelProperty("姓名") // 按列名匹配 private String name; @ExcelProperty(index = 1) // 按列索引匹配(第二列) private Integer age; } ``` > **注意**:列名匹配时,需确保Excel表头完全一致(包括空格和大小写)。若表头有重复,必须使用`index`属性区分。 ### 步骤2:验证依赖冲突 在`pom.xml`中检查EasyExcel依赖,并排除冲突的POI模块: ```xml <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>4.0.3</version> <exclusions> <!-- 排除冲突的POI依赖 --> <exclusion> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml-schemas</artifactId> </exclusion> </exclusions> </dependency> ``` > 引用[2]提到EasyExcel 3+版本需手动排除`poi-ooxml-schemas`,4.0.3同样适用。同时确保项目中其他依赖的POI版本为5.x+。 ### 步骤3:检查数据格式 - 使用Excel打开文件,确认: 1. 表头在第一行且无合并单元格。 2. 数据区域无空行或非标准格式(如公式、超链接)。 - 若文件非标准,可尝试另存为`.xlsx`格式再读取。 ### 步骤4:调试自定义转换器 若使用了自定义转换器(Converter),检查其实现是否正确: ```java public class CustomStringConverter implements Converter<String> { @Override public String convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { // 示例:将数字转为字符串 if (cellData.getType() == CellDataTypeEnum.NUMBER) { return cellData.getNumberValue().toString(); } return cellData.getStringValue(); } } ``` 并在实体类字段上指定: ```java @ExcelProperty(value = "工资", converter = CustomStringConverter.class) private String salary; ``` ### 步骤5:启用监听器日志 在读取Excel时注册`AnalysisEventListener`,通过日志定位失败行: ```java EasyExcel.read(file, User.class, new UserDataListener()).sheet().doRead(); ``` 监听器实现示例: ```java public class UserDataListener extends AnalysisEventListener<User> { @Override public void invoke(User user, AnalysisContext context) { System.out.println("解析到数据: " + user); } @Override public void onException(Exception exception, AnalysisContext context) { System.out.println("解析失败,继续下一行: " + exception.getMessage()); } } ``` ## 常见错误场景及修复 1. **字段为`null`但Excel有值** - 原因:字段名与表头不匹配 → 检查`@ExcelProperty`的`value`值。 2. **类型转换异常(如`String`转`Date`失败)** - 解决方案:使用`@DateTimeFormat("yyyy-MM-dd")`注解日期字段。 3. **读取到部分数据后中断** - 原因:数据行存在空值或格式错误 → 在监听器中捕获异常并跳过。 ## 总结 通过以上步骤,90%的映射问题可解决。若仍失败,建议: - 升级EasyExcel到最新稳定版(如`4.1.1`)。 - 最小化测试:仅保留一个字段验证基础映射。 §§相关问题§§ 1. EasyExcel 如何读取包含合并单元格的Excel文件? 2. 如何用EasyExcel导出大数据量(百万行)的Excel3. EasyExcel与POI的性能对比有哪些优势? [^1]: 文章目录 什么是 EasyExcelEasyExcel 的特点使用EasyExcel导出excel1.添加EasyExcel依赖2.定义converter3.定义导出实体类型4.查询数据库数据并导出5.导出样式 [^2]: 重要提示:3+版本easyexcel,且使用 poi 5+版本时,需自己引入 poi 5+版本的包,并手动排除 poi-ooxml-schemas。</think>### EasyExcel 4.0.3 数据映射实体类失败的原因及解决方法 #### 常见原因分析 1. **注解配置问题** - 未正确使用 `@ExcelProperty` 注解标注实体类字段 - 注解中的 `index`(列索引)或 `value`(列名)与实际 Excel 列不匹配 - 缺少必要的转换器注解(如日期字段未加 `@DateTimeFormat`) 2. **依赖冲突** - POI 版本冲突(如引用[2]所述,EasyExcel 4.x 需要 POI 5.2+) - 其他库(如 Apache POI)版本EasyExcel 不兼容 ```xml <!-- 正确依赖配置示例 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>4.0.3</version> <exclusions> <exclusion> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> </exclusion> </exclusions> </dependency> <!-- 手动引入 POI 5.2+ --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>5.2.3</version> </dependency> ``` 3. **数据类型不匹配** - Excel 中的数字/日期格式与实体类字段类型不一致 - 空单元格处理不当(如基本类型 int 遇到空值会报错) 4. **表头结构问题** - 多行表头未配置 `headRowNumber` 参数 - 动态表头未使用 `@ExcelIgnoreUnannotated` 注解 #### 解决方案 **1. 检查实体类注解配置** ```java public class User { // 按列名映射(需完全匹配表头) @ExcelProperty("姓名") private String name; // 按列索引映射(从0开始) @ExcelProperty(index = 1) private Integer age; // 日期格式转换 @ExcelProperty("注册日期") @DateTimeFormat("yyyy-MM-dd") private Date registerDate; } ``` **2. 解决依赖冲突** - 执行 Maven 依赖树分析: ```bash mvn dependency:tree -Dincludes=org.apache.poi ``` - 确保 POI 相关依赖统一为 5.2.x 版本 **3. 添加自定义转换器**(处理特殊格式) ```java public class CustomStringConverter implements Converter<String> { @Override public String convertToJavaData(ReadCellData<?> cellData) { // 处理空单元格 if (cellData.getType() == CellDataTypeEnum.EMPTY) { return ""; } // 数字转字符串 return cellData.getStringValue(); } } // 在实体类中使用 @ExcelProperty(value = "电话", converter = CustomStringConverter.class) private String phone; ``` **4. 调整读取配置** ```java EasyExcel.read(file) .head(User.class) // 设置表头行数(多行表头时) .headRowNumber(2) // 忽略空行 .ignoreEmptyRow(true) .sheet() .doRead(); ``` **5. 调试与日志** - 启用监听器调试数据: ```java public class UserListener extends AnalysisEventListener<User> { @Override public void invoke(User user, AnalysisContext context) { System.out.println("解析到数据: " + user); } @Override public void onException(Exception exception, AnalysisContext context) { System.out.println("解析失败: " + exception.getMessage()); } } ``` #### 验证流程 1. 简化测试:用仅含 1 列的 Excel 验证基础映射 2. 逐步增加字段,定位问题列 3. 检查 `@ExcelIgnore` 注解是否误排除必要字段 4. 使用 EasyExcel 的 `ReadListener` 获取原始单元格数据: ```java context.readRowHolder().getCellMap().forEach((k,v) -> System.out.println(k + ":" + v)); ``` > 通过以上步骤,90% 的映射问题可解决。若仍失败,建议升级到 EasyExcel 最新版(当前4.1.1)[^1][^2]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值