java.lang.AbstractMethodError: Receiver class org.apache.poi.xssf.streaming.SXSSFWorkbook

#  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 或更早),两者不兼容。

详细解释:

  1. 接口与实现分离:SXSSFWorkbook 这个类属于 poi-ooxml Jar 包。Workbook 和 Font 接口属于 poi (核心) Jar 包。

  2. 方法签名变更:在 POI 的版本迭代中,getFontAt(int) 这个方法在 Workbook 接口中的定义可能发生了变化。最关键的是,在 POI 4.x 版本中,这个方法的返回值可能从 Font 变成了具体的实现类(如 XSSFFont),或者其内部实现逻辑发生了不兼容的变更。

  3. 版本不匹配的后果:

    • 你的代码在编译时,编译器看到的是 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款的旧发动机(旧实现)。发动机虽然能装上去(类能加载),但它的燃油喷射系统(方法实现)无法与新车的电脑(新接口的期望)通信,导致汽车报错无法启动。

为什么会出现这种部分升级的情况?

这种情况非常常见,通常是因为:

  1. Maven 传递依赖:你的项目可能直接依赖了 poi:4.1.2,但同时另一个依赖(比如某个旧的报表工具、工具包)传递引入了旧版本的 poi-ooxml,而 Maven 的依赖调解机制没有选择最高版本。

  2. 手动管理 Jar 包:如果你不是用 Maven/Gradle,而是手动管理 Jar 包,你可能只替换了 poi-4.1.2.jar,但没有替换 poi-ooxml-*.jarpoi-ooxml-schemas-*.jar 等配套的 Jar 包。

  3. 明确指定了旧版本:可能在你的 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>

 

诊断和验证步骤

  1. 运行 Maven 依赖树命令:
    在项目根目录下执行:

    bash
    mvn dependency:tree -Dincludes=org.apache.poi*

    仔细查看输出结果。你会清晰地看到每个 POI 组件被引用的版本。你会发现在 poi 下面显示的是 4.1.2,而在 poi-ooxml 下面很可能是一个更旧的版本(比如 3.17)。

  2. 解决冲突:

    • 如果是因为传递依赖导致的旧版本,你需要在你的依赖声明中显式地、强制地声明 poi-ooxml 的版本为 4.1.2(如上代码所示)。Maven 的就近原则会使用你明确指定的版本。

    • 如果某个第三方库强制依赖了非常旧的 POI,你可能需要在这个第三方依赖中使用 <exclusions> 来排除掉旧的 POI 传递依赖。

      <dependency>
          <groupId>some.problematic.group</groupId>
          <artifactId>problematic-artifact</artifactId>
          <version>1.0</version>
          <exclusions>
              <exclusion>
                  <groupId>org.apache.poi</groupId>
                  <artifactId>*</artifactId> <!-- 排除所有poi传递依赖 -->
              </exclusion>
          </exclusions>
      </dependency>

       

  3. 清理和重新部署:

    • 执行 mvn clean install

    • 检查最终打包的 WAR 或 JAR 文件中的 WEB-INF/lib 目录,确认里面所有的 poi-*.jar 文件版本都是 4.1.2

    • 重新部署应用到服务器并重启。

总结:你遇到的问题是一个经典的“部分升级”导致的二进制不兼容问题。解决方案就是将所有 POI 相关组件的版本保持绝对一致。

 
posted @ 2025-09-05 08:50  哩个啷个波  阅读(40)  评论(0)    收藏  举报