# 1.报错内容
(DirectJDKLog.java:175) Servlet.service() for servlet [UReportServlet] in context with path [/cld/repairWheelsetService] threw exception [Servlet execution threw an exception] with root cause
java.lang.AbstractMethodError: Receiver class org.apache.poi.xssf.streaming.SXSSFWorkbook does not define or inherit an implementation of the resolved method abstract getFontAt(I)Lorg/apache/poi/ss/usermodel/Font; of interface org.apache.poi.ss.usermodel.Workbook.
# 2.原因
是我私自升级了pom.xml文件中的依赖导致的错误
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.2</version>
</dependency>
不要随意升级依赖,或者升级前应该了解该依赖绑定升级的其他依赖有哪些
# 3.AI解释,还算准确
根本原因是:你只升级了 poi (核心库) 到 4.1.2,但没有同步升级 poi-ooxml (处理 .xlsx 文件的库)。你的项目中存在一个版本的 poi (4.1.2) 和一个旧版本的 poi-ooxml (很可能是 3.17 或更早),两者不兼容。
详细解释:
-
接口与实现分离:SXSSFWorkbook 这个类属于 poi-ooxml Jar 包。Workbook 和 Font 接口属于 poi (核心) Jar 包。
-
方法签名变更:在 POI 的版本迭代中,getFontAt(int) 这个方法在 Workbook 接口中的定义可能发生了变化。最关键的是,在 POI 4.x 版本中,这个方法的返回值可能从 Font 变成了具体的实现类(如 XSSFFont),或者其内部实现逻辑发生了不兼容的变更。
-
版本不匹配的后果:
-
你的代码在编译时,编译器看到的是 POI 4.1.2 的 Workbook 接口,它知道 getFontAt(int) 方法返回一个 Font。
-
但在运行时,JVM 加载的是旧版本的 poi-ooxml 中的 SXSSFWorkbook 类。
-
这个旧版本的 SXSSFWorkbook 是在旧版 POI (如 3.17) 下编译的,它实现的 getFontAt(int) 方法签名(返回值类型或方法逻辑)与新版 POI 4.1.2 的 Workbook 接口的期望不匹配。
-
JVM 发现该方法没有正确实现接口的约定,因此抛出 AbstractMethodError。
简单比喻:
这就像你给一辆2023款的新车(新接口)换了一个2010款的旧发动机(旧实现)。发动机虽然能装上去(类能加载),但它的燃油喷射系统(方法实现)无法与新车的电脑(新接口的期望)通信,导致汽车报错无法启动。
为什么会出现这种部分升级的情况?
这种情况非常常见,通常是因为:
-
Maven 传递依赖:你的项目可能直接依赖了 poi:4.1.2,但同时另一个依赖(比如某个旧的报表工具、工具包)传递引入了旧版本的 poi-ooxml,而 Maven 的依赖调解机制没有选择最高版本。
-
手动管理 Jar 包:如果你不是用 Maven/Gradle,而是手动管理 Jar 包,你可能只替换了 poi-4.1.2.jar,但没有替换 poi-ooxml-*.jar、poi-ooxml-schemas-*.jar 等配套的 Jar 包。
-
明确指定了旧版本:可能在你的 POM 文件中,对 poi-ooxml 有一个明确的、版本号更旧的依赖声明。
解决方案:统一所有 POI 组件的版本
你必须确保所有 Apache POI 相关的组件都来自完全相同的版本(这里是 4.1.2)。
在 Maven 的 pom.xml 中,你应该这样声明依赖:
<properties>
<!-- 在一个地方统一定义版本,方便管理 -->
<poi.version>4.1.2</poi.version>
</properties>
<dependencies>
<!-- 核心库 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>${poi.version}</version>
</dependency>
<!-- 处理 .xlsx 文件的核心库 (包含了SXSSFWorkbook) -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>${poi.version}</version>
</dependency>
<!-- 如果需要处理 .docx 文件,也请保持版本一致 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>${poi.version}</version>
</dependency>
<!-- 其他POI组件,如poi-excelant等,也需同步版本 -->
</dependencies>
诊断和验证步骤
-
运行 Maven 依赖树命令:
在项目根目录下执行:
mvn dependency:tree -Dincludes=org.apache.poi*
仔细查看输出结果。你会清晰地看到每个 POI 组件被引用的版本。你会发现在 poi 下面显示的是 4.1.2,而在 poi-ooxml 下面很可能是一个更旧的版本(比如 3.17)。
-
解决冲突:
-
清理和重新部署:
总结:你遇到的问题是一个经典的“部分升级”导致的二进制不兼容问题。解决方案就是将所有 POI 相关组件的版本保持绝对一致。