项目总结之maven冲突

作者: Java面试官 | 来源:发表于2017-05-25 02:01 被阅读3277次

    描述

    今天遇见了一个相对而言有点奇葩的问题,一个pom文件的依赖配置,如果是以下配置的话:

    image.png

    则发布成功,一点问题都没有,如果是以下配置的话:

    image.png

    则会抛出以下异常:

    java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]]
        at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:252) [na:1.7.0_17]
        at java.util.concurrent.FutureTask.get(FutureTask.java:111) [na:1.7.0_17]
        at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:939) ~[tomcat-embed-core-8.5.14.jar:8.5.14]
        at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:872) [tomcat-embed-core-8.5.14.jar:8.5.14]
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) [tomcat-embed-core-8.5.14.jar:8.5.14]
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1419) [tomcat-embed-core-8.5.14.jar:8.5.14]
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1409) [tomcat-embed-core-8.5.14.jar:8.5.14]
        at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334) [na:1.7.0_17]
        at java.util.concurrent.FutureTask.run(FutureTask.java:166) [na:1.7.0_17]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [na:1.7.0_17]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [na:1.7.0_17]
        at java.lang.Thread.run(Thread.java:722) [na:1.7.0_17]
    Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]]
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) [tomcat-embed-core-8.5.14.jar:8.5.14]
        ... 7 common frames omitted
    Caused by: org.apache.catalina.LifecycleException: Failed to start component [Pipeline[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]]]
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) [tomcat-embed-core-8.5.14.jar:8.5.14]
        at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5117) ~[tomcat-embed-core-8.5.14.jar:8.5.14]
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) [tomcat-embed-core-8.5.14.jar:8.5.14]
        ... 7 common frames omitted
    Caused by: org.apache.catalina.LifecycleException: Failed to start component [org.apache.catalina.authenticator.NonLoginAuthenticator[]]
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) [tomcat-embed-core-8.5.14.jar:8.5.14]
        at org.apache.catalina.core.StandardPipeline.startInternal(StandardPipeline.java:182) ~[tomcat-embed-core-8.5.14.jar:8.5.14]
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) [tomcat-embed-core-8.5.14.jar:8.5.14]
        ... 9 common frames omitted
    Caused by: java.lang.NoSuchMethodError: javax.servlet.ServletContext.getVirtualServerName()Ljava/lang/String;
        at org.apache.catalina.authenticator.AuthenticatorBase.startInternal(AuthenticatorBase.java:1141) ~[tomcat-embed-core-8.5.14.jar:8.5.14]
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) [tomcat-embed-core-8.5.14.jar:8.5.14]
        ... 11 common frames omitted
    

    通过师兄的指点加上多方查证了解到是依赖冲突了,现在具体描述下查证的过程:

    image.png

    由以上的堆栈异常可以看出,在加载依赖的时候javax.servlet.ServletContext少了个getVirtualServerName()函数,于是我定位到tomcat-embed-core-8.5.14.jar这个依赖下

    image.png

    发现tomcat-embed-core-8.5.14.jar这个依赖下的ServletContext是有getVirtualServerName函数的,那么为什么这里还提示找不到呢?我猜测是因为jar包冲突,在加载tomcat-embed-core-8.5.14.jar下的ServletContext之前就先加载了其他jar包的ServletContext了,于是查找了相关的依赖,在:

    image.png

    找到了ServletContext接口,确实是没有getVirtualServerName这个函数,跟我上面的预想基本一致。


    那么问题来了,为什么反过来就可以了?

    于是我又去谷歌了,得知以下两个知识点:
    1、依赖路径最短优先原则
    一个项目Demo依赖了两个jar包,其中A-B-C-X(1.0) , A-D-X(2.0)。由于X(2.0)路径最短,所以项目使用的是X(2.0)。
    2、pom文件中声明顺序优先
    如果A-B-X(1.0) ,A-C-X(2.0) 这样的路径长度一样怎么办呢?这样的情况下,maven会根据pom文件声明的顺序加载,如果先声明了B,后声明了C,那就最后的依赖就会是X(1.0)。

    于是我总结到,应该是依赖路径长短一样,导致跟pom文件中声明的顺序有关。

    相信很多人和我一样,在犹豫如何查找依赖路径,以下推荐一种:

    使用Intellij idea,想看看它的maven依赖图,打开的pom.xml文件,在pom文件内容上右键Diagrams–Show Dependencies,就可以看到了。如:

    image.png

    由图也可以看出,依赖路径也确实一样。

    总结:遇见问题要大胆的去请教,通过系统反馈的异常深入的研究问题出在哪里,而不只是解决了问题就好!


    Note:发布的这些文章全都是自己边学边总结的,难免有纰漏,如果发现有不足的地方,希望可以指出来,一起学习咯,么么哒。
    开源爱好者,相信开源的力量必将改变世界:
    ** osc :** https://git.oschina.net/xi_fan

    相关文章

      网友评论

        本文标题:项目总结之maven冲突

        本文链接:https://www.haomeiwen.com/subject/wndaxxtx.html