java-maven-idea: 在 jar 中包含外部库
java-maven-idea: including external library in jar
我正在制作电报机器人,我需要 .jar 将其部署到云端。
我正在使用 intellij idea 中的 maven 构建它,但是当尝试在我的机器上执行时它会抛出这个:
Exception in thread "main" java.lang.NoClassDefFoundError: org/telegram/telegrambots/bots/TelegramLongPollingBot<br>
据我了解,发生这种情况是因为 Maven 没有将此库打包到 .jar 中。
我该怎么做?
粗略地说,你有两个选择
- 制作一个包含所有必需 类 的“胖”JAR
- 制作一个引用其他 JAR 文件的“瘦”JAR
最适合您的情况只有您才能决定。操作方法如下:
制作一个包含所有必需 类 的“胖”JAR
要遵循此方法,请使用 Maven Shade Plugin. In the package phase, you would invoke its shade
goal。这会将 类 从您的依赖项以及您的应用程序 类 一起复制到一个 JAR-file 中。它在 POM 中可能看起来像这样:
<executions>
<execution>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<finalName>my-packaged-application</finalName>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.mycompany.MyApplication</mainClass>
</transformer>
</transformers>
<filters>
<filter>
<!--
Shading signed JARs will fail without this.
-->
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
</configuration>
</execution>
</executions>
这种方法的优点是您的应用程序被打包为一个文件。缺点是比较大。即使您只为新版本更改几行代码,整个文件也会不同。
制作一个引用其他 JAR 文件的“瘦”JAR
在这种方法中,JAR 仅包含您的应用程序 类。它的清单文件引用类路径,但您还需要为依赖项提供 JAR 文件。要收集这些,请使用 Maven Dependency Plugin, more specifically the copy-dependencies
goal。您可以这样配置它:
<executions>
<execution>
<id>copy</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/libs</outputDirectory>
<stripVersion>true</stripVersion>
</configuration>
</execution>
</executions>
现在您在 target/lib 中拥有所有依赖项 JAR 文件,最后一件事是确保“瘦”JAR 引用这些文件。为此,配置 Maven Jar Plugin:
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>com.mycompany.MyApplication</mainClass>
</manifest>
</archive>
</configuration>
在这种方法中,如果您只更改几行应用程序代码,则只会替换应用程序 JAR - 依赖项 JAR 保持不变。不利的一面是,它要求您分发的不是一个文件,而是一个目录结构:应用程序 JAR 文件以及 lib/ 文件夹及其内容。
我正在制作电报机器人,我需要 .jar 将其部署到云端。
我正在使用 intellij idea 中的 maven 构建它,但是当尝试在我的机器上执行时它会抛出这个:
Exception in thread "main" java.lang.NoClassDefFoundError: org/telegram/telegrambots/bots/TelegramLongPollingBot<br>
据我了解,发生这种情况是因为 Maven 没有将此库打包到 .jar 中。
我该怎么做?
粗略地说,你有两个选择
- 制作一个包含所有必需 类 的“胖”JAR
- 制作一个引用其他 JAR 文件的“瘦”JAR
最适合您的情况只有您才能决定。操作方法如下:
制作一个包含所有必需 类 的“胖”JAR
要遵循此方法,请使用 Maven Shade Plugin. In the package phase, you would invoke its shade
goal。这会将 类 从您的依赖项以及您的应用程序 类 一起复制到一个 JAR-file 中。它在 POM 中可能看起来像这样:
<executions>
<execution>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<finalName>my-packaged-application</finalName>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.mycompany.MyApplication</mainClass>
</transformer>
</transformers>
<filters>
<filter>
<!--
Shading signed JARs will fail without this.
-->
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
</configuration>
</execution>
</executions>
这种方法的优点是您的应用程序被打包为一个文件。缺点是比较大。即使您只为新版本更改几行代码,整个文件也会不同。
制作一个引用其他 JAR 文件的“瘦”JAR
在这种方法中,JAR 仅包含您的应用程序 类。它的清单文件引用类路径,但您还需要为依赖项提供 JAR 文件。要收集这些,请使用 Maven Dependency Plugin, more specifically the copy-dependencies
goal。您可以这样配置它:
<executions>
<execution>
<id>copy</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/libs</outputDirectory>
<stripVersion>true</stripVersion>
</configuration>
</execution>
</executions>
现在您在 target/lib 中拥有所有依赖项 JAR 文件,最后一件事是确保“瘦”JAR 引用这些文件。为此,配置 Maven Jar Plugin:
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>com.mycompany.MyApplication</mainClass>
</manifest>
</archive>
</configuration>
在这种方法中,如果您只更改几行应用程序代码,则只会替换应用程序 JAR - 依赖项 JAR 保持不变。不利的一面是,它要求您分发的不是一个文件,而是一个目录结构:应用程序 JAR 文件以及 lib/ 文件夹及其内容。