如何定位及解决依赖版本冲突

本文目的

依赖版本冲突如何定位、如何解决


今天有个同事遇到一个诡异的事情,就是明明引用代码有那个方法但运行总报错找不到java.lang.NoSuchMethodError,盲猜版本冲突(遇到很多次都是版本冲突)

问题复现

代码依赖

     <dependencies>
     
<!--                easy-excel   https://github.com/alibaba/easyexcel-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>3.3.3</version>
        </dependency>
        <!--        word 填充依赖-->
        <dependency>
            <groupId>cn.afterturn</groupId>
            <artifactId>easypoi-base</artifactId>
            <version>4.1.2</version>
        </dependency>
    </dependencies>
 

测试代码

package com.csh.test.project.word;

import cn.afterturn.easypoi.word.WordExportUtil;
import cn.afterturn.easypoi.word.entity.MyXWPFDocument;
import cn.hutool.core.lang.Assert;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ClassPathResource;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * @author free-bird
 * @version 1.0
 * @date 2023/3/9 3:05 PM
 */
@Slf4j
public class WordUtils {

    /**
     * @param params
     * @param sourceTemplatePath 源文件模板,resources下全路径
     * @return
     */
    public static String fillParam(Map<String, Object> params, String sourceTemplatePath) {
        Assert.notNull(sourceTemplatePath, "来源文件不能为空");
        ClassPathResource classPathResource = new ClassPathResource(sourceTemplatePath);
        // 新建临时目录
        String tmpDir = "./tmp/";
        File file = new File(tmpDir);
        if (!file.exists() && file.mkdir()) {
            log.info("创建./tmp目录完成");
        }
        String suffix = sourceTemplatePath.substring(sourceTemplatePath.lastIndexOf("."));
        String tmpPath = tmpDir + UUID.randomUUID().toString() + suffix;
        try (InputStream inputStream = classPathResource.getInputStream();
             FileOutputStream fos = new FileOutputStream(tmpPath)) {
            MyXWPFDocument doc = new MyXWPFDocument(inputStream);
            WordExportUtil.exportWord07(doc, params);
            doc.write(fos);
        } catch (Exception e) {
            log.error("word fill param exception: ", e);
            throw new RuntimeException("word fill param exception");
        }
        return tmpPath;
    }

    public static void main(String[] args) {
        Map<String, Object> map = new HashMap<>();
        map.put("name", "小明");
        //doc格式不支持
        //org.apache.poi.openxml4j.exceptions.OLE2NotOfficeXmlFileException: The supplied data appears to be in the OLE2 Format. You are calling the part of POI that deals with OOXML (Office Open XML) Documents. You need to call a different part of POI to process this data (eg HSSF instead of XSSF)
        //随便在resources下创建一个模板testWordTemplate.docx,内容{{name}}
        WordUtils.fillParam(map, "./testWordTemplate.docx");
    }
}
运行报错,
Exception in thread "main" java.lang.NoSuchMethodError: org.apache.poi.util.XMLHelper.newDocumentBuilder()Ljavax/xml/parsers/DocumentBuilder;
	at org.apache.poi.ooxml.util.DocumentHelper.newDocumentBuilder(DocumentHelper.java:47)
	at org.apache.poi.ooxml.util.DocumentHelper.<clinit>(DocumentHelper.java:36

定位问题与解决

通过报错分析问题

XMLHelper.newDocumentBuilder()找不到方法,跟踪到org.apache.poi.ooxml.util.DocumentHelper#newDocumentBuilder,里面 return XMLHelper.newDocumentBuilder();导航到XMLHelper,发现有这个方法的呀!

 

那大概率是版本冲突了, 但为什么导航过去是有这个方法的,双击shirt全局搜索类XMLHelper,好家伙真的有两个类但不同版本进去发现4.1.2是有这个方法,而4.1.0里没有。

 

确认问题

应该是加载到4.1.0版本了,但是如何确认的 两个方式: 1.debug 2.使用插件Maven Helper

1、debug

将断点放在org.apache.poi.ooxml.util.DocumentHelper#newDocumentBuilder这,运行debug模式

 

到了断点打开表达是求值放入 DocumentHelper.class.getClassLoader().findClass("org.apache.poi.util.XMLHelper") 再求值如图所示,再点导航,发现进入的是4.1.0版本

 

2、Maven Helper

点击pom.xml左下角有Dependency Analyzer再选择Conflicts(展示冲突),左边是冲突内容,右边是来自哪个依赖及其版本层级以及最终使用了哪个依赖(红色方块就是实际使用的依赖版本)

 

解决

排查poi依赖,因为easypoi-base只是用来填充word模板参数而引入的easyexcel则是主要用来操作excel所以将easypoi-base中依赖版本移除减少出问题的概率(排除依赖需要考虑影响范围,如果都没影响排除谁都无所谓) 排除poi-ooxml-schemas也一样 排除完 点击上面Reimport刷新依赖,等Refresh UI有个感叹号再点击刷新,冲突没有了,再运行则正常结束

 

 

最终pom文件

<dependencies>
<!--                easy-excel   https://github.com/alibaba/easyexcel-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>3.3.3</version>
        </dependency>
        <!--        word 填充依赖-->
        <dependency>
            <groupId>cn.afterturn</groupId>
            <artifactId>easypoi-base</artifactId>
            <version>4.1.2</version>
            <exclusions>
                <exclusion>
                    <artifactId>poi</artifactId>
                    <groupId>org.apache.poi</groupId>
                </exclusion>
                <exclusion>
                    <artifactId>poi-ooxml-schemas</artifactId>
                    <groupId>org.apache.poi</groupId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

🤗 总结归纳

java.lang.NoSuchMethodError遇到这个报错基本是版本冲突没得跑,除非是少了依赖 所以需要根据错误分析问题再对症下药,合理使用插件,提高解决问题效率

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值