IntelliJ单元测试中Apache POI与Commons-IO的Charsets.toCharset()方法缺失问题
核心问题
切换到SXSSFWorkbook后触发NoSuchMethodError,本质是Commons-IO版本冲突:代码依赖2.15.1版本的Charsets.toCharset(Charset, Charset)方法,但运行时加载了2.5/2.6等低版本Commons-IO,这些版本不存在该方法。
深层原因
父POM依赖管控失效的本质
父POM的dependencyManagement仅能统一子项目未显式声明版本的依赖,若子项目的传递依赖中出现低版本Commons-IO,且父POM的dependencyManagement未明确指定该依赖的版本,Maven会按「路径最短优先」或「声明顺序优先」规则选择低版本,而非自动继承父POM的默认版本。另外,若父POM中Commons-IO的groupId/artifactId书写错误、范围(scope)设置不当,也会导致覆盖失效。SXSSFWorkbook触发新的依赖冲突路径
从XSSFWorkbook切换到SXSSFWorkbook后,POI的依赖链发生变化——SXSSF会引入额外的POI-OOXML相关依赖,这些依赖可能通过间接路径拉取低版本Commons-IO,且这条路径未被父POM的版本覆盖规则命中。Maven/IntelliJ缓存干扰
本地Maven仓库已存在低版本Commons-IO,即使mvn dependency:tree显示冲突被忽略,IntelliJ运行单元测试时可能直接读取本地缓存的旧Jar包,而非Maven解析后的正确版本。此外,IntelliJ的Maven自动导入若未及时更新,也会导致运行时依赖与依赖树不一致。
彻底解决方案
1. 修复父POM的依赖版本管控
在父POM的dependencyManagement中明确声明Commons-IO及POI相关依赖的版本,强制所有子项目统一使用指定版本:
<dependencyManagement> <dependencies> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-io</artifactId> <version>2.15.1</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>5.2.3</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>5.2.3</version> </dependency> </dependencies> </dependencyManagement>
此配置会覆盖所有传递依赖引入的低版本,确保全项目依赖版本一致。
2. 清理缓存并强制更新
- 手动清理本地Maven缓存:删除
~/.m2/repository/org/apache/commons/commons-io下所有非2.15.1的文件夹; - 执行Maven命令强制更新:
mvn clean install -U-U参数会强制Maven刷新依赖,避免使用缓存的旧版本; - 刷新IntelliJ的Maven依赖:点击右侧Maven面板的「Reload All Maven Projects」,确保IDE加载最新配置。
3. 验证依赖一致性
执行以下命令,仅检查Commons-IO的依赖路径,确认所有引用均为2.15.1:
mvn dependency:tree -Dincludes=org.apache.commons:commons-io
若仍有低版本出现,找到对应的依赖来源,在子项目中通过exclusions排除低版本:
<dependency> <!-- 填入引入低版本Commons-IO的父依赖信息 --> <groupId>xxx</groupId> <artifactId>xxx</artifactId> <exclusions> <exclusion> <groupId>org.apache.commons</groupId> <artifactId>commons-io</artifactId> </exclusion> </exclusions> </dependency>
4. 用Maven Enforcer插件强制版本统一(可选)
在父POM中添加Enforcer插件,配置规则禁止引入低版本Commons-IO,从根源避免冲突:
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-enforcer-plugin</artifactId> <version>3.3.0</version> <executions> <execution> <id>enforce-dependencies</id> <goals> <goal>enforce</goal> </goals> <configuration> <rules> <requireDependencyVersion> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-io</artifactId> <version>[2.15.1,)</version> </dependency> </requireDependencyVersion> </rules> </configuration> </execution> </executions> </plugin> </plugins> </build>
5. 检查IntelliJ运行配置
确保单元测试的运行配置中,Classpath基于Maven依赖生成,无手动添加的旧Jar包:
- 打开Run/Debug Configurations → 选择对应单元测试 → 查看「Classpath」标签页,确认仅包含Maven管理的依赖。
内容的提问来源于stack exchange,提问作者mcv

