Java 使用 Gradle 创建可运行的 JAR

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21721119/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 10:17:01  来源:igfitidea点击:

Creating runnable JAR with Gradle

javajargradle

提问by Hannes

Until now I created runnable JAR files via the Eclipse "Export..." functionallity but now I switched to IntelliJ IDEA and Gradle for build automation.

到目前为止,我通过 Eclipse“导出...”功能创建了可运行的 JAR 文件,但现在我切换到 IntelliJ IDEA 和 Gradle 以实现构建自动化。

Some articles here suggest the "application" plugin, but this does not entirely lead to the result I expected (just a JAR, no start scripts or anything like this).

这里的一些文章建议使用“应用程序”插件,但这并没有完全导致我预期的结果(只是一个 JAR,没有启动脚本或类似的东西)。

How can I achieve the same result Eclipse does with the "Export..." dialog?

如何获得与 Eclipse 使用“导出...”对话框相同的结果?

采纳答案by JB Nizet

An executable jar file is just a jar file containing a Main-Class entry in its manifest. So you just need to configure the jar taskin order to add this entry in its manifest:

一个可执行的 jar 文件只是一个在其清单中包含一个 Main-Class 条目的 jar 文件。因此,您只需要配置jar 任务即可在其清单中添加此条目:

jar {
    manifest {
        attributes 'Main-Class': 'com.foo.bar.MainClass'
    }
}

You might also need to add classpath entries in the manifest, but that would be done the same way.

您可能还需要在清单中添加类路径条目,但这将以相同的方式完成。

See http://docs.oracle.com/javase/tutorial/deployment/jar/manifestindex.html

请参阅http://docs.oracle.com/javase/tutorial/deployment/jar/manifestindex.html

回答by Jorge_B

Have you tried the 'installApp' task? Does it not create a full directory with a set of start scripts?

您是否尝试过“installApp”任务?它不会创建一个包含一组启动脚本的完整目录吗?

http://www.gradle.org/docs/current/userguide/application_plugin.html

http://www.gradle.org/docs/current/userguide/application_plugin.html

回答by davidmc24

Both JB Nizet and Jorge_B's answers are correct.

JB Nizet 和 Jorge_B 的答案都是正确的。

In its simplest form, creating an executable JAR with Gradle is just a matter of adding the appropriate entries to the manifest. However, it's much more common to have dependencies that need to be included on the classpath, making this approach tricky in practice.

在最简单的形式中,使用 Gradle 创建可执行 JAR 只是将适当的条目添加到manifest 的问题。但是,需要将依赖项包含在类路径中的情况更为常见,这使得这种方法在实践中变得棘手。

The application pluginprovides an alternate approach; instead of creating an executable JAR, it provides:

应用的插件提供了一种替代方法; 它没有创建可执行的 JAR,而是提供:

  • a runtask to facilitate easily running the application directly from the build
  • an installDisttask that generates a directory structure including the built JAR, all of the JARs that it depends on, and a startup script that pulls it all together into a program you can run
  • distZipand distTartasks that create archives containing a complete application distribution (startup scripts and JARs)
  • 一项run便于直接从构建中轻松运行应用程序的任务
  • 一个installDist生成目录结构的任务,包括构建的 JAR、它依赖的所有 JAR,以及一个启动脚本,该脚本将所有这些组合到一个您可以运行的程序中
  • distZip以及distTar创建包含完整应用程序分发(启动脚本和 JAR)的档案的任务

A third approach is to create a so-called "fat JAR" which is an executable JAR that includes not only your component's code, but also all of its dependencies. There are a few different plugins that use this approach. I've included links to a few that I'm aware of; I'm sure there are more.

第三种方法是创建一个所谓的“胖 JAR”,它是一个可执行的 JAR,不仅包含组件的代码,还包含其所有依赖项。有几个不同的插件使用这种方法。我已经包含了一些我知道的链接;我确定还有更多。

回答by Mondain

You can define a jar artifact in the module settings (or project structure).

您可以在模块设置(或项目结构)中定义一个 jar 工件。

  • Right click the module > Open module settings > Artifacts > + > JAR > from modules with dependencies.
  • Set the main class.
  • 右键单击模块 > 打开模块设置 > 工件 > + > JAR > 来自具有依赖项的模块。
  • 设置主类。

Making a jar is then as easy as clicking "Build artifact..." from the Build menu. As a bonus, you can package all the dependencies into a single jar.

制作 jar 就像从 Build 菜单中单击“Build artifact...”一样简单。作为奖励,您可以将所有依赖项打包到一个 jar 中。

Tested on IntelliJ IDEA 14 Ultimate.

在 IntelliJ IDEA 14 Ultimate 上测试。

回答by Martin Andersson

As others have noted, in order for a jar file to be executable, the application's entry point must be set in the Main-Classattribute of the manifest file. If the dependency class files are not collocated, then they need to be set in the Class-Pathentry of the manifest file.

正如其他人所指出的,为了使 jar 文件可执行,必须Main-Class在清单文件的属性中设置应用程序的入口点。如果依赖类文件没有并置,则需要Class-Path在manifest文件的条目中进行设置。

I have tried all kinds of plugin combinations and what not for the simple task of creating an executable jar and somehow someway, include the dependencies. All plugins seem to be lacking one way or another, but finally I got it like I wanted. No mysterious scripts, not a million different mini files polluting the build directory, a pretty clean build script file, and above all: not a million foreign third party class files merged into my jar archive.

我已经尝试了各种插件组合,而不是为了创建可执行 jar 的简单任务,并以某种方式包含依赖项。所有插件似乎都缺乏一种或另一种方式,但最终我得到了我想要的。没有神秘的脚本,没有一百万个不同的小文件污染构建目录,一个非常干净的构建脚本文件,最重要的是:没有一百万个外国第三方类文件合并到我的 jar 档案中。

The following is a copy-paste from herefor your convenience..

为了您的方便,以下是从这里复制粘贴..

[How-to] create a distribution zip file with dependency jars in subdirectory /liband add all dependencies to Class-Pathentry in the manifest file:

[How-to] 在子目录中创建一个带有依赖项 jar 的分发 zip 文件,/lib并将所有依赖Class-Path项添加到清单文件的条目中:

apply plugin: 'java'
apply plugin: 'java-library-distribution'

repositories {
    mavenCentral()
}

dependencies {
    compile 'org.apache.commons:commons-lang3:3.3.2'
}

// Task "distZip" added by plugin "java-library-distribution":
distZip.shouldRunAfter(build)

jar {
    // Keep jar clean:
    exclude 'META-INF/*.SF', 'META-INF/*.DSA', 'META-INF/*.RSA', 'META-INF/*.MF'

    manifest {
        attributes 'Main-Class': 'com.somepackage.MainClass',
                   'Class-Path': configurations.runtime.files.collect { "lib/$it.name" }.join(' ')
    }
    // How-to add class path:
    //     https://stackoverflow.com/questions/22659463/add-classpath-in-manifest-using-gradle
    //     https://gist.github.com/simon04/6865179
}

Hosted as a gist here.

在这里作为要点托管。

The result can be found in build/distributionsand the unzipped contents look like this:

结果可以在中找到,build/distributions解压后的内容如下所示:

lib/commons-lang3-3.3.2.jar
MyJarFile.jar

lib/commons-lang3-3.3.2.jar
MyJarFile.jar

Contents of MyJarFile.jar#META-INF/MANIFEST.mf:

内容MyJarFile.jar#META-INF/MANIFEST.mf

Manifest-Version: 1.0
Main-Class: com.somepackage.MainClass
Class-Path: lib/commons-lang3-3.3.2.jar

清单版本:1.0
主类:com.somepackage.MainClass
类路径:lib/commons-lang3-3.3.2.jar

回答by Ostkontentitan

Least effort solution for me was to make use of the gradle-shadow-plugin

对我来说最省力的解决方案是使用gradle-shadow-plugin

Besides applying the plugin all that needs to be done is:

除了应用插件,所有需要做的是:

Configure the jar task to put your Main class into manifest

配置 jar 任务以将您的 Main 类放入清单

jar {
  manifest {
   attributes 'Main-Class': 'com.my.app.Main'
  }
}

Run the gradle task

运行gradle任务

./gradlew shadowJar

Take the app-version-all.jarfrom build/libs/

build/libs/获取app-version-all.jar

And finally execute it via:

最后通过以下方式执行它:

java -jar app-version-all.jar

回答by Alex Yavorskiy

Thank you Konstantin, it worked like a charm with few nuances. For some reason, specifying main class as part of jar manifest did not quite work and it wanted the mainClassName attribute instead. Here is a snippet from build.gradle that includes everything to make it work:

谢谢康斯坦丁,它就像一种魅力,几乎没有细微差别。出于某种原因,将主类指定为 jar 清单的一部分并不完全有效,而是需要 mainClassName 属性。这是 build.gradle 中的一个片段,其中包含使其工作的所有内容:

plugins {
  id 'java' 
  id 'com.github.johnrengelman.shadow' version '1.2.2'
}
...
...
apply plugin: 'application'
apply plugin: 'com.github.johnrengelman.shadow'
...
...
mainClassName = 'com.acme.myapp.MyClassMain'
...
...
...
shadowJar {
    baseName = 'myapp'
}

After running gradle shadowJar you get myapp-{version}-all.jar in your build folder which can be run as java -jar myapp-{version}-all.jar.

运行 gradle shadowJar 后,您将在构建文件夹中获得 myapp-{version}-all.jar,该文件夹可以作为 java -jar myapp-{version}-all.jar 运行。

回答by Sandeep Sarkar

I checked quite some links for the solution, finally did the below mentioned steps to get it working. I am using Gradle 2.9.

我检查了很多解决方案的链接,最后执行了下面提到的步骤以使其正常工作。我正在使用 Gradle 2.9。

Make the following changes in your build,gradle file :

在您的 build,gradle 文件中进行以下更改:

  1. Mention plugin:

    apply plugin: 'eu.appsatori.fatjar'
    
  2. Provide the Buildscript:

    buildscript {
    repositories {
        jcenter()
    }
    
    dependencies {
        classpath "eu.appsatori:gradle-fatjar-plugin:0.3"
    }
    }
    
  3. Provide the Main Class:

    fatJar {
      classifier 'fat'
      manifest {
        attributes 'Main-Class': 'my.project.core.MyMainClass'
      }
      exclude 'META-INF/*.DSA', 'META-INF/*.RSA', 'META-INF/*.SF'
    }
    
  4. Create the fatjar:

    ./gradlew clean fatjar
    
  5. Run the fatjar from /build/libs/ :

    java -jar MyFatJar.jar
    
  1. 提及插件:

    apply plugin: 'eu.appsatori.fatjar'
    
  2. 提供构建脚本:

    buildscript {
    repositories {
        jcenter()
    }
    
    dependencies {
        classpath "eu.appsatori:gradle-fatjar-plugin:0.3"
    }
    }
    
  3. 提供主类:

    fatJar {
      classifier 'fat'
      manifest {
        attributes 'Main-Class': 'my.project.core.MyMainClass'
      }
      exclude 'META-INF/*.DSA', 'META-INF/*.RSA', 'META-INF/*.SF'
    }
    
  4. 创建胖子:

    ./gradlew clean fatjar
    
  5. 从 /build/libs/ 运行 fatjar:

    java -jar MyFatJar.jar
    

回答by Topera

You can use the SpringBoot plugin:

您可以使用 SpringBoot 插件:

plugins {
  id "org.springframework.boot" version "2.2.2.RELEASE"
}

Create the jar

创建罐子

gradle assemble

And then run it

然后运行它

java -jar build/libs/*.jar

Note: your project does NOT need to be a SpringBoot project to use this plugin.

注意:您的项目不需要是 SpringBoot 项目即可使用此插件。