关于maven中pom依赖冲突问题记录
一、场景
最近需要开发一个word 报告设计和展示功能模块,决定采用poi-tl 开源框架,引用集成该pom依赖后出现问题。
二、问题分析
根据poi-tl 官方文档说明:
https://deepoove.com/poi-tl/#_maven
添加依赖
<dependency>
<groupId>com.deepoove</groupId>
<artifactId>poi-tl</artifactId>
<version>1.12.2</version>
</dependency>
后执行demo 代码,生成word 文档报错如下:
org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.NoSuchMethodError: 'org.apache.poi.xwpf.usermodel.XWPFComments org.apache.poi.xwpf.usermodel.XWPFDocument.getDocComments()'
官网中最后的常见问题说明,此种问题一般都是poi 版本冲突,其框架依赖版本为apache-poi版本是5.2.2+
于是开始排查pom 依赖冲突,关于这个之前一直没有去认真研究,有时候解决了冲突,有时候是别人帮忙最后解决的。
这次周末一个人在办公室花时间来调试,刚开始一直以为是和easyExcel 这个依赖冲突了,但是实际上,这个只是在通用模块里面做了声明,自己调试的服务并没有直接依赖。
通过咨询大模型,其提供的方式是要在服务模块的pom.xml 中强制声明需要的依赖版本,于是做了如下处理:
<poi.version>5.2.5</poi.version>
<!-- 统一指定 Apache POI 版本 -->
<dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>${poi.version}</version>
</dependency>
<dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>${poi.version}</version>
</dependency>
这样运行后,再次调用接口,报错如下:
org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.NoClassDefFoundError: org/apache/commons/io/output/UnsynchronizedByteArrayOutputStream
看起来又是commons-io 版本有问题,不过这个貌似不是版本冲突,而是版本太低了,可能poi-tl 中依赖的版本是比较高的,调用了一些高版本的方法,后面调试陆续还遇到如下错误:
org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.NoSuchMethodError: 'org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream$Builder org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream.builder()'
Caused by: java.lang.NoSuchMethodError: 'void org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream.putArchiveEntry(org.apache.commons.compress.archivers.zip.ZipArchiveEntry)'
于是根据大模型提供的方式,将commons-io 和 commons-compress 版本改为对应较高的版本,最终接口成功调用。

其实这样改完正常运行之后,在idea 的pom 依赖检查界面中还是能看到一些模块的冲突版本,刚开始我以为都要一个个exclude掉,后来调试发现将这些排除去掉也是可以正常运行的。说明pom中定义的强制版本已经生效,这里面只是间接依赖导致的,IDEA 就会标注出一个“潜在冲突”提示。
三、总结
核心原理:Maven 依赖冲突规则
先明确 Maven 解决冲突的默认逻辑,避免无效操作:
- 路径最短优先:直接依赖(项目
pom.xml显式声明)优先级高于间接依赖(依赖的依赖)。 - 声明顺序优先:路径长度相同时,
pom.xml中声明在前的依赖生效。 - 版本锁定优先:通过
<dependencyManagement>声明的版本会覆盖其他版本(推荐用这种方式统一版本)。
冲突本质:多个依赖传递引入了同一依赖的不同版本,导致类加载异常(如 ClassNotFoundException、NoSuchMethodError)。
除了idea 中的插件查看外,其实也可以通过mvn 命令来查看,但是要注意setting 配置文件将自己本地的私有仓库路径配置对,不然用默认的可能会报错。
/mvn dependency:tree -Dincludes=commons-io

其实还有疑惑就是,为啥引用了poi-tl 1.12版本,看了其源码中对poi 的依赖是5.2.2

为啥业务服务中看到的依赖还是4.2 版本...
