163

我听说人们说他们创建了一个胖 JAR 并部署它。它们实际上是什么意思?

4

6 回答 6

107

fat jar 是 jar,它包含来自所有库的类,您的项目依赖于这些库,当然还有当前项目的类。

在不同的构建系统中,胖 jar 的创建方式不同,例如,在 Gradle 中,可以使用(指令)创建它:

task fatJar(type: Jar) {
    manifest {
        attributes 'Main-Class': 'com.example.Main'
    }
    baseName = project.name + '-all'
    from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
    with jar
}

在 Maven 中,它是这样做的(在设置常规 jar 之后):

<pluginRepositories>
   <pluginRepository>
        <id>onejar-maven-plugin.googlecode.com</id>
        <url>http://onejar-maven-plugin.googlecode.com/svn/mavenrepo</url>
   </pluginRepository>

<plugin>
    <groupid>org.dstovall</groupid>
    <artifactid>onejar-maven-plugin</artifactid>
    <version>1.4.4</version>
    <executions>
        <execution>
            <configuration>
                <onejarversion>0.97</onejarversion>
                <classifier>onejar</classifier>
            </configuration>
            <goals>
                <goal>one-jar</goal>
            </goals>
        </execution>
   </executions>
</plugin>
于 2015-04-28T16:53:29.533 回答
92

不同的名称只是打包 Java 应用程序的方式。

Skinny – 仅包含您在代码编辑器中真正输入的位,没有其他内容。

Thin – 包含上述所有内容以及应用程序对您的应用程序的直接依赖项(数据库驱动程序、实用程序库等)。

Hollow – Thin 的倒数 – 仅包含运行您的应用程序所需的位,但不包含应用程序本身。基本上是一个预打包的“应用程序服务器”,您可以稍后将应用程序部署到该服务器,其风格与传统 Java EE 应用程序服务器相同,但有重要区别。

Fat/Uber 包含你自己写的部分加上你的应用程序的直接依赖项加上“独立”运行你的应用程序所需的部分。

资料来源:Dzone 文章

JAR 类型的可视化表示

于 2019-08-21T12:54:22.800 回答
17

Fat jar 或 uber jar 是一个 jar,它包含所有项目类文件和资源以及它的所有依赖项。有不同的方法可以达到这种效果:

  • 依赖项的 jar 被复制到主 jar 中,然后使用特殊的类加载器(onejar,spring-boot-plugin:repackage)加载
  • 依赖项的 jar 在主 jar 层次结构的顶部提取(maven-assembly-plugin 及其 jar-with-dependencies 程序集)
  • 依赖项的 jar 在主 jar 层次结构的顶部被解包,并且它们的包被重命名(带有 shade 目标的 maven-shade-plugin)

下面的示例程序集插件配置jar-with-dependencies

<project>
  ...
  <build>
    ...
    <plugins>
      <plugin>
        <!-- NOTE: We don't need a groupId specification because the group is
             org.apache.maven.plugins ...which is assumed by default.
         -->
        <artifactId>maven-assembly-plugin</artifactId>
        <version>2.6</version>
        <configuration>
          <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
          </descriptorRefs>
          <classifier
        </configuration>
        ...
</project>

更详细的解释:imagej.net 上的 Uber-JAR

于 2016-04-11T04:31:58.637 回答
10

在可执行 jar 的情况下,考虑胖 jar 的另一种方法是您可以通过调用执行:

java -jar myFatLibrary.jar

不需要-cp/ --classpath,甚至不需要双击 jar 图标。

于 2016-07-10T16:23:55.207 回答
0

胖 jar 只包含与经典 jar 相同的类 + 来自所有运行时依赖项的类。

使用 Jeka ( https://jeka.dev ),您可以通过编程方式实现它:

JkPathTreeSet.of(Paths.get("classes")).andZips(
    Paths.get("bouncycastle-pgp-152.jar"),
    Paths.get("classgraph-4.8.41.jar"),
    Paths.get("ivy-2.4.0.jar")
).zipTo(Paths.get("fat.jar"));

或者只是通过参数化 Java 插件:

javaPlugin.getProject().getMaker().defineMainArtifactAsFatJar(true);
于 2019-07-09T16:30:56.683 回答
0

来自Gradle 文档

在 Java 空间中,应用程序及其依赖项通常被打包为单个分发存档中的单独 JAR。这仍然会发生,但是现在有另一种常见的方法:将依赖项的类和资源直接放入应用程序 JAR 中,创建所谓的 uber 或 fat JAR。

uberJar这是文件中任务的演示 build.gradle

task uberJar(type: Jar) {
    archiveClassifier = 'uber'

    from sourceSets.main.output

    dependsOn configurations.runtimeClasspath
    from {
        configurations.runtimeClasspath.findAll { it.name.endsWith('jar') }.collect { zipTree(it) }
    }
}

在这种情况下,我们将获取项目的运行时依赖项configurations.runtimeClasspath.files——并使用该方法包装每个 JAR 文件zipTree()。结果是 ZIP 文件树的集合,其内容与应用程序类一起复制到 uber JAR 中。

于 2019-10-15T04:16:29.563 回答