【Apache POI 填坑日记】NoSuchMethodError: UnsynchronizedByteArrayOutputStream.builder() 排查与解决

【Apache POI 填坑日记】NoSuchMethodError: UnsynchronizedByteArrayOutputStream.builder() 排查与解决

作者:@Neoest
时间:2025-08-02
关键词:Apache POI、Excel、NoSuchMethodError、commons-io、依赖冲突


1. 问题现场

周五晚上集成测试,测试小姐姐突然在群里 @ 我:

“导出 Excel 怎么又 500 了?”

我打开日志,瞬间眼前一黑:

Caused by: java.lang.NoSuchMethodError: 'org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream$Builder org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream.builder()'
        at org.apache.poi.xssf.usermodel.XSSFWorkbook.newPackage(XSSFWorkbook.java:544)
        at org.apache.poi.xssf.usermodel.XSSFWorkbook.<init>(XSSFWorkbook.java:231)
        at com.xxx.service.ExcelService.export(ExcelService.java:88)

异常栈截图:

后台报错


2. 先定位代码

出问题的代码极其简单,就是一行:

XSSFWorkbook workbook = new XSSFWorkbook();

错误提示很明确:UnsynchronizedByteArrayOutputStream.builder() 这个静态方法在运行时找不到。


3. 为什么报错?

NoSuchMethodError 是典型的 运行时依赖冲突 问题:

  • 编译时有commons-io-2.11.0.jar 中的 UnsynchronizedByteArrayOutputStream 确实有 builder()
  • 运行时没有:实际加载的是 旧版本(如 2.8.0),老版本没有这个方法。

4. 三种解决方案

✅ 方案 A:升级 commons-io(推荐)

步骤 1:查看当前依赖树

mvn dependency:tree -Dincludes=commons-io:commons-io

输出:

[INFO] +- org.apache.poi:poi-ooxml:5.2.5
[INFO] |  \- commons-io:commons-io:2.11.0
[INFO] +- your.company:legacy-sdk:1.0.0
[INFO]    \- commons-io:commons-io:2.8.0

Maven 的 nearest-winner 策略导致 2.8.0 被选中。

步骤 2:统一版本

pom.xml<dependencyManagement> 中加:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.15.1</version>
        </dependency>
    </dependencies>
</dependencyManagement>

或直接声明:

<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.15.1</version>
</dependency>

步骤 3:验证

mvn dependency:tree -Dincludes=commons-io:commons-io

确保只剩一个版本:

commons-io:commons-io:2.15.1

重新运行,导出成功!

✅ 方案 B:排除旧传递依赖(不推荐)
<dependency>
    <groupId>your.company</groupId>
    <artifactId>legacy-sdk</artifactId>
    <version>1.0.0</version>
    <exclusions>
        <exclusion>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
        </exclusion>
    </exclusions>
</dependency>

缺点:如果别的库又依赖旧版,还得继续排,治标不治本。

✅ 方案 C:使用 BOM 统一 POI 版本

如果你项目里 POI 版本也混乱,可以用官方 BOM:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-bom</artifactId>
            <version>5.2.5</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

5. 小结

方案适用场景侵入性备注
升级 commons-io90% 场景最推荐
排除传递依赖临时修复治标不治本
使用 BOM多 POI 模块一劳永逸

6. 一键复制版补丁

<!-- pom.xml -->
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.15.1</version>
</dependency>

7. 参考资料

如果本文帮到你,记得点赞收藏!评论区一起交流更多 POI 坑位~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Neoest

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值