老版本 EasyExcel 一个神出鬼没的异常 - 教程

news/2025/10/13 15:30:29/文章来源:https://www.cnblogs.com/tlnshuju/p/19138595

老版本 EasyExcel 一个神出鬼没的异常 - 教程

2025-10-13 15:25  tlnshuju  阅读(0)  评论(0)    收藏  举报

1 背景

数据中台上线以来,总有一个 同步作业 偶尔会抛出异常:com.alibaba.excel.exception.ExcelAnalysisException: Converter not found, convert STRING to java.lang.String

在这里插入图片描述

作业通过 datax 同步用户在 ftp 上传的文件数据到数据中台;datax 会调用使用 EasyExcel 库加载 Excel 文件的数据,并在加载过程中偶尔抛出异常。

异常是由于无法找到,把 Excel 中的 字符串 Cell 转换为 java 字符串 的 转换器,这就很奇怪,这应该是一个最基本的转换器了。

这个 神出鬼没 的异常,有以下几个特点:

  • 只有固定的 同步作业 会抛出异常,其余的同步作业都运行正常;
  • 这个异常是偶发的,每个月会发生 4-5 次;
  • 作业由于异常运行失败后 5 分钟,再重试,就成功了,非常诡异。

虽然,重试机制可以保证作业最终是运行成功的,但,只要抛出这个异常,整条数据链路的完成时间就会延迟。因此,必须找出导致异常的 root cause。

2 根本原因分析

2.1 EasyExcel 的源码分析

首先,数据中台当前使用的 EasyExcel 版本是 2.1.4,已经是 2019 年的老版本了:
在这里插入图片描述

(1) 分析异常栈

在这里插入图片描述
异常由 ConverterUtils 的 130 行抛出,具体代码如下:
在这里插入图片描述
由于无法从 converterMap 中获取转换器,从而抛出 ExcelDataConvertException 异常。

converterMap 里面保存了 Excel Cell 数据类型 - java 类型转换器 的对应关系。

因此需要分析 converterMap 是如何被初始化的,有可能在运行到 ConverterUtils 的 130 行 时,converterMap 仍未完成初始化,导致无法获取 转换器

(2) 分析 converterMap 如何初始化

  • converterMap 来自 AbstractHolder 类:
    在这里插入图片描述
  • converterMap 的初始化时机

在读取 Excel 数据时,会实例化类 ReadSheetHolder,它是 AbstractHolder 的子类(ReadSheetHolder -继承-> AbstractReadHolder -继承-> AbstractHolder

在实例化 ReadSheetHolder 时,会调用 AbstractReadHolder 的构造器:
在这里插入图片描述
AbstractReadHolder 的构造器会调用 DefaultConverterLoader.loadDefaultReadConverter()converterMap 进行赋值。

(3) DefaultConverterLoader 初始化 转换器Map

在这里插入图片描述

  • 首先,loadDefaultReadConverter 是类级别的静态方法;
  • loadDefaultReadConverter 最终会调用 loadAllConverter 方法;
  • loadAllConverter 会判断静态属性 allConverter 是否为 null,如果非 null 则直接返回 allConverter,否则初始化 allConverter 中的转换器。

(4) 异常根本原因分析

  • 首先,作业是要同步文件夹中的 4 个文件到数据中台,并发度为 3,即同时会有 3 个线程同步文件,因此,loadAllConverter 运行在一个多线程的场景下;
  • loadAllConverter 方法没有做线程安全处理;
  • 会出现一种情况,线程 A 执行到
allConverter = new HashMap<String, Converter>(64);

B线程刚好执行到

if (allConverter != null) {
return allConverter;
}

就返回了空的 allConverter 了,由此,导致无法找到 转换器,而抛出 ExcelDataConvertException 异常。

这种由于没有做线程安全处理而导致的异常,也符合它神出鬼没的特性。

2.2 本地复现异常

2.2.1 先在 maven 引入数据中台版本的 EasyExcel 依赖

<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.1.4</version>
</dependency>

2.2.2 编写测试代码

package com.nutanix.test;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
/**
* 使用EasyExcel读取Excel文件并转换为Map集合的工具类
*/
public class ExcelToMapReader {
/**
* 读取Excel文件并转换为List<Map<String, Object>>* @param filePath Excel文件路径* @return 包含Excel数据的Map集合列表,每个Map对应一行数据*/public static List<Map<String, Object>> readExcelToMap(String filePath) {// 创建一个监听器实例ExcelMapListener listener = new ExcelMapListener();// 读取Excel文件EasyExcel.read(filePath, listener).sheet() // 读取第一个sheet.doRead(); // 执行读取操作// 返回读取到的数据return listener.getDataList();}/*** 自定义监听器,用于处理Excel读取事件*/private static class ExcelMapListener extends AnalysisEventListener<Map<String, Object>> {// 存储读取到的数据private List<Map<String, Object>> dataList = new ArrayList<>();/*** 每读取一行数据都会调用此方法* @param data 一行数据,键是表头,值是单元格内容* @param context 分析上下文*/@Overridepublic void invoke(Map<String, Object> data, AnalysisContext context) {dataList.add(data);}/*** 读取完成后调用此方法* @param context 分析上下文*/@Overridepublic void doAfterAllAnalysed(AnalysisContext context) {// 可以在这里添加读取完成后的处理逻辑System.out.println("Excel文件读取完成,共读取 " + dataList.size() + " 行数据");}/*** 获取读取到的数据列表* @return 数据列表*/public List<Map<String, Object>> getDataList() {return dataList;}}public static void main(String[] args) throws InterruptedException {Thread thread = new Thread(() -> {readExcelToMap("/tmp/customer-file1.xlsx");});Thread thread2 = new Thread(() -> {readExcelToMap("/tmp/customer-file2.xlsx");});Thread thread3 = new Thread(() -> {readExcelToMap("/tmp/customer-file3.xlsx");});Thread thread4 = new Thread(() -> {readExcelToMap("/tmp/customer-file4.xlsx");});thread.start();thread2.start();thread3.start();thread4.start();}}

程序模拟数据中台的作业,启动 4 个线程,分别读取对应的 excel 文件。

2.2.3 打断点

DefaultConverterLoaderloadAllConverter() 打断点:
在这里插入图片描述

2.2.4 调试

3 新版本的 EasyExcel 处理

在新版本的 EasyExcel,阿里团队已经通过采用静态代码块的方式,在 DefaultConverterLoader 首次被访问时,对 allConverter 进行了初始化,从而解决了在并发环境的线程安全问题:
在这里插入图片描述

4 总结

至此,根因已经找到了,就是因为,老版本的 EasyExcel,在初始化 类型与转换器的 Map 对象时,没有做线程安全处理,导致,在并发环境下,ExcelDataConvertException 异常神出鬼没地出现。

希望本文,对其他遇到这个问题的同学有帮助。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/936193.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2025 年粮库空调厂家最新推荐榜:聚焦技术创新与实用适配,助力粮库精准选购优质设备粮库空调一体机/粮库空调机组/碳钢喷塑粮库空调/低温粮库空调厂家推荐

引言粮食储备安全关乎国计民生,而粮库空调作为保障粮食品质、减少存储损耗的核心设备,其性能优劣直接影响粮食存储效果。当前市场上粮库空调厂家数量繁杂,产品质量、技术水平与服务能力差异显著,部分产品存在温湿度…

2025 年最新推荐!泳池除湿热泵厂家推荐榜单重磅发布,全方位解析优质厂家实力助您选对设备双模式/多功能/三集一体/全直流变频/室内/变频式泳池除湿热泵厂家推荐

引言 随着室内泳池的普及,泳池环境温湿度控制成为关键难题。高湿度不仅影响游泳者舒适度,还会损害建筑结构、滋生霉菌,传统设备能耗高且控温除湿效果差。如今市场上泳池除湿热泵品牌杂乱,产品质量、技术水平参差不…

django template filter safe escapejs json_script等

========safe==============|safe 可以当作html的tag渲染 ====in view: context[user_content1]="<b>Hello</b>"context[user_content2]="<b>Hello</b>"return render(re…

2025年GEO(AI搜索优化)厂家口碑推荐排行榜

摘要 随着人工智能技术的飞速发展,GEO(AI搜索优化)行业在2025年迎来爆发式增长,企业纷纷寻求高效、低成本的AI搜索优化解决方案以提升数字营销效果。本文基于用户搜索数据和行业调研,为您推荐2025年口碑最佳的GEO…

2025年GEO(AI搜索优化)源头厂家权威推荐榜单:云视有客科技领跑行业新纪元

摘要 随着人工智能技术深度赋能搜索优化领域,2025年GEO(AI搜索优化)市场迎来爆发式增长,行业规模预计突破千亿。本文基于技术参数、服务效能和用户口碑三维度评估,为您权威解析国内优质GEO源头厂家,其中云视有客…

2025年GEO服务商口碑推荐榜单:顶尖AI搜索优化厂家全方位解析

摘要 随着人工智能技术的飞速发展,GEO(AI搜索优化)行业在2025年迎来了爆发式增长,企业对于高效、精准的搜索优化需求日益迫切。本文基于市场调研和用户反馈,为您推荐2025年口碑最佳的GEO服务商,并提供详细排行榜…

2025年GEO(AI搜索优化)厂家口碑推荐榜:云视有客科技领跑行业创新

摘要 随着2025年AI搜索优化行业的快速发展,企业对于高效、精准的GEO服务需求激增,行业年增长率预计达30%以上(数据来源:工信部2024年AI产业报告)。本文基于用户搜索意图,提供2025年GEO厂家口碑排行榜单,并附上详…

2025企业聊天软件排行 5款好用的通讯软件推荐

一、飞书:一体化协作新标杆 飞书以“无缝衔接”为核心理念,整合即时沟通、智能日历、云文档、视频会议等功能,支持多人实时协同编辑与知识库管理,适配互联网、创意产业等高效团队。 特点优势智能文档协同:云文档支…

【触想智能】工业安卓一体机在人工智能领域上的市场应用分析

工业安卓一体机在人工智能(AI)领域上具有广泛的市场应用潜力。工业安卓一体机是指集成了安卓操作系统的硬件设备,具备强大的计算和数据处理能力,适用于各种工业环境。触想工业安卓一体机TPC-A2系列以下是关于工业安卓…

Redis中的线程模型 - 浪矢

目录什么是Redis?Redis性能优秀的原因1 内存数据库2 高效的I/O模型3 简洁高效的通信协议 (Simple Protocol - RESP)Redis的线程模型 什么是Redis? Redis是NoSQL的数据库,数据保存在内存中(支持RDB,AOF),因此读写…

2025 年油气回收设备厂家最新推荐排行榜:加油站 / 油库 / 码头 / 化工厂适用优质品牌精选

引言当前环保政策日趋严格,油气挥发造成的能源浪费与污染问题已成为石油化工、加油站等行业发展的重要制约因素。然而,市场上油气回收设备品牌繁杂,部分产品存在回收效率低、环保不达标、售后无保障等问题,导致企业…

Vue3 + OpenLayers + 天地图 简单集成

1.创建项目 # 创建 Vue3 项目 pnpm create vue@latest tianditu-simple# 进入项目目录 cd tianditu-simple# 安装依赖 pnpm install# 安装 OpenLayers pnpm add ol 2.创建地图组件 <!-- src/components/MapContaine…

基于 PyTorch 完全从零手搓 GPT 混合专家 (MOE) 对话模型 - 详解

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

Linux环境下安装Jenkins2.346.3

1. 安装JDK:下载JDK并解压后,配置/etc/profile环境变量export JAVA_HOME=/usr/java/jdk1.8.0_202 export PATH=$JAVA_HOME/bin:$PATH export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar2. 安装tom…

2025 年疲劳试验机厂家最新推荐排行榜:涵盖液压 / 电动 / 扭转等多类型设备,助力企业精准挑选优质厂家

当前工业制造、航空航天、汽车等领域对材料与部件疲劳性能测试的需求日益严苛,疲劳试验机作为核心检测设备,其质量直接决定测试数据的可靠性。但市场上该类制造商数量繁杂,部分企业缺乏核心技术,设备稳定性差、售后…

2025 年万能试验机厂家最新推荐排行榜:涵盖电子 / 液压 / 拉力 / 压力 / 冲击等类型,助力企业科研机构精准选购优质设备

当前工业制造升级、材料研发创新及科研试验深入推进,万能试验机作为把控产品质量、评估材料性能、保障科研数据准确的关键设备,其重要性愈发凸显。但市场上品牌繁杂,部分产品存在技术滞后、精度不达标、售后响应慢等…

2025 年涡流分离器源头厂家最新推荐排行榜:聚焦国内优质企业,助力制造企业精准采购可靠分离设备旋转分配器/油路分配器/离心过滤器厂家推荐

在当前精密制造行业快速发展的背景下,涡流分离器作为保障生产效率、产品精度与环保合规的关键设备,其市场需求持续增长。但市场上源头厂家数量繁杂,部分企业存在技术不成熟、品控不严格、售后响应慢等问题,导致制造…

欧美(美股、加拿大股票、墨西哥股票)股票数据接口文档

概述 StockTV 提供全面的欧美股票市场数据接口,覆盖美国、加拿大、墨西哥等主要欧美市场。支持实时行情、技术分析、公司信息等多种功能。 国家与交易所对应关系 美国市场NYSE (纽约证券交易所): 交易所ID 1 NASDAQ (…

2025年GEO(AI搜索优化)服务商口碑排行榜

摘要 随着人工智能技术的飞速发展,GEO(AI搜索优化)行业在2025年迎来爆发式增长,企业对于高效、低成本的AI搜索优化需求激增。本文基于行业数据和用户反馈,为您呈现2025年GEO服务商口碑排行榜,帮助您快速找到可靠…

为了这0.1 dB,他在实验室蹲了整整8年

为了这0.1 dB,他在实验室蹲了整整8年——国产5G衰减器实现0.1 dB精度替代,现货库存已上线 李维8年只干一件事:把误差降到0.1 dB。 2016年,28岁的射频工程师李维辞去上海 50 万年薪,带着一箱示波器来到成都恒利泰科…