javamaven理念:在jar中包含外部库

pjngdqdw  于 2021-07-08  发布在  Java
关注(0)|答案(1)|浏览(248)

我正在制作电报机器人,我需要.jar在云中部署它。
我正在用intellij idea中的maven构建它,但是当尝试在我的机器上执行时,它抛出了以下内容:

Exception in thread "main" java.lang.NoClassDefFoundError: org/telegram/telegrambots/bots/TelegramLongPollingBot<br>

据我所知,这是因为maven没有将这个lib打包到.jar中。
我该怎么做?

ktca8awb

ktca8awb1#

粗略地说,你有两个选择
制作一个包含所有必需类的“胖”jar
制作一个引用其他jar文件的“瘦”jar
什么是最适合你的情况是只有你能决定。以下是您的操作方法:

制作一个包含所有必需类的“胖”jar

为了遵循这种方法,您可以使用maven shade插件。在包阶段,您将调用 shade 目标。这将把依赖关系中的类以及应用程序类一起复制到一个jar文件中。在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.
            http://stackoverflow.com/questions/999489/invalid-signature-file-when-attempting-to-run-a-jar
          -->
          <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依赖插件,更具体地说是 copy-dependencies 目标。您可以这样配置:

<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插件:

<configuration>
  <archive>
    <manifest>
      <addClasspath>true</addClasspath>
      <classpathPrefix>lib/</classpathPrefix>
      <mainClass>com.mycompany.MyApplication</mainClass>
    </manifest>
  </archive>
</configuration>

在这种方法中,如果只更改应用程序代码的几行,那么只会替换应用程序jar,而依赖关系jar则保持不变。另一方面,它要求您分发的不是一个文件而是一个目录结构:applicationjar文件以及lib/文件夹及其内容。

相关问题