java—intellij如何在命令行中解析依赖项并运行SpringBoot(maven)应用程序,这是不可能的?

7cjasjjr  于 2021-07-14  发布在  Java
关注(0)|答案(1)|浏览(297)

我很想知道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文件)
谢谢

qoefvg9y

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 参数)。这允许您部署应用程序,使应用程序安装看起来像:

/usr/local/projects/YourApp/main-app.jar
/usr/local/projects/YourApp/dep/guava.jar
/usr/local/projects/YourApp/dep/mysql-jdbc-connector.jar
/usr/local/projects/YourApp/dep/jdbi.jar

等等,要运行这个应用程序,只需运行 main-app.jar . 这需要main-app.jar的清单包含以下条目:

Class-Path: dep/guava.jar dep/mysql-jdbc-connector.jar dep/jdbi.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的解决方案,我不推荐它。

相关问题