我很想知道intellij如何解决依赖冲突?让我解释一下我的情况。我应该在spring引导应用程序上工作。它使用maven。intellij可以毫无问题地构建和运行应用程序,但是当我创建jar文件时,
mvn clean package
然后运行jar文件
java -jar xxx.jar
我面对一个 java.lang.NoSuchMethodError
. 依赖关系上的一些冲突导致了这种情况,我的应用程序使用了错误版本的jar文件。我想知道intellij如何找到包含该方法的正确jar文件,同时它使用相同的pom.xml,我在使用mvn命令时遇到错误。有没有可能找到intellij使用的每个jar文件的哪个版本(我想用它来更正pom文件)
谢谢
1条答案
按热度按时间qoefvg9y1#
运行时和编译时有很大的区别。
编译代码(例如
mvn package
),并编写代码(例如,intellij正在做什么来确保您的编辑体验良好;对于您使用的所有库,自动完成对话框、尝试调用不存在的方法时出现的错误等等)是一回事(我们称之为“写入时间”)。运行代码,比如
java -jar .jar
完全不同。maven和你的依赖列表是一个写时间的东西。因此,maven和intellij知道在哪里查找依赖项,但是当您运行
java -jar .jar
,不知道在哪里查找,因此找不到依赖项,因此,NoClassDefFoundError
发生。这是因为maven生成的jar文件只包含您的代码,它与maven文件完全断开连接(当您运行代码时,您的maven内容根本不会被查找),并且它不包含您的依赖项。
你得分开装运。有3种解决方案:
首选解决方案:jar文件包含一个所谓的manifest,它告诉jvm该jar文件中的主类的名称。它还可以包含类路径(这实际上是使用
java -jar
运行jar文件;不能指定-classpath
参数)。这允许您部署应用程序,使应用程序安装看起来像:等等,要运行这个应用程序,只需运行
main-app.jar
. 这需要main-app.jar的清单包含以下条目:运行jar时
Class-Path
条目按空格拆分,然后相对于包含的目录查找每个条目main-app.jar
. 通过单独运送jar,可以很容易地单独更新或替换它们,并且部署新版本的速度要快得多(只需运送更改过的jar,而不是所有jar)。许多应用程序都有数百mb的DEP,而它们自己的jar最多只有几mb,这会产生很大的差异(例如,当将DEP从您的开发人员机器推送到测试服务器时!)这就引出了一个问题:如何让maven将类路径条目放在输出jar文件的清单中?这个
maven-jar-plugin
可以做这项工作-查看此答案了解更多详细信息。在你的deps(也称为条纹,或fatjar,或bigjar)
这就是这样一个概念:获取所有的dep,重写它们的名称以避免版本冲突,然后生成一个包含所有内容的庞大jar文件。它有一个相当大的缺点,那就是进程要慢得多,特别是当您需要将它推到另一个系统进行测试时。使用shade插件来执行此操作。
不要使用
java -jar
.java -jar x.jar
除非jar文件在其清单中有一个类路径条目,或者包含它需要的每个dep,否则无法工作。但是,您也可以这样运行java代码:java -cp main-app.jar:dep/guava.jar:dep/jdbi.jar:/dep/other-deps-here com.foo.YourMainApp
. 这是。。不方便,但您可以编写一个shell脚本或类似的脚本。这不是一个非常类似java的解决方案,我不推荐它。