运行 Gradle 编译的 Java 应用程序,通过 java 命令具有依赖项
Running a Gradle compiled Java application with dependencies via the java command
我正在尝试从 this article explaining the Swing Application Framework (JSR 296) with Gradle 编译代码示例 3,然后使用 java
命令从命令行将其编译为 运行。
我的目录布局如下所示:
├── build.gradle
└── src/
└── main/
└── java/
└── demo/
└── BasicSingleFrameApp.java
build.gradle
文件定义了对 appframework
:
的依赖
apply plugin: 'java'
repositories {
mavenCentral()
}
dependencies {
compile 'org.jdesktop:appframework:1.0.3'
}
这是 BasicSingleFrameApp.java
文件,上面提到的文章示例的副本,由包声明增强:
package demo;
import org.jdesktop.application.*;
import javax.swing.*;
import java.awt.*;
public class BasicSingleFrameApp extends SingleFrameApplication {
JLabel label;
@Override
protected void startup() {
getMainFrame().setTitle("BasicSingleFrameApp");
label = new JLabel("Hello, world!");
label.setFont(new Font("SansSerif", Font.PLAIN, 22));
show(label);
}
public static void main(String[] args) {
Application.launch(BasicSingleFrameApp.class, args);
}
}
使用 gradle build
编译工作正常且没有错误。
但是当我尝试 运行 BasicSingleFrameApp
和
$ java -cp build/classes/main/ demo.BasicSingleFrameApp
我收到错误消息:
Error: Could not find or load main class demo.BasicSingleFrameApp
当我用简单的“Hello, world!”替换 BasicSingleFrameApp
class 时在没有依赖项的情况下打印 class,一切正常。
我很困惑,因为据我所知,我正确设置了 class 路径,但我不明白为什么找不到 main
方法(具有正确的签名)。
这是我的 Java 版本:
java version "1.8.0_20"
Java(TM) SE Runtime Environment (build 1.8.0_20-b26)
Java HotSpot(TM) 64-Bit Server VM (build 25.20-b23, mixed mode)
我正在 运行宁 Mac OS X Yosemite 10.10.2.
据我所知,您正在使用 java 启动应用程序,因此您必须告诉 java 在哪里可以找到您下载的 swing 应用程序框架 jar。所以命令应该看起来像
java -cp pathtojdektopjar/jdesktopjar.jar;build/classes/main/ demo.BasicSingleFrameApp
好的,所以@chuchikaeschtli 帮助我找到了问题的核心,即 Gradle 管理编译的依赖项并报告在 运行 时间内这样做,但更多的手动任务是需要在 运行 时间内使这些依赖项可用。
仍然让我感到困惑的是我收到的不直观的错误消息:
Error: Could not find or load main class demo.BasicSingleFrameApp
我本以为会在 运行 时出现与缺少依赖项有关的问题,然后报告
之类的错误
error: package org.jdesktop.application does not exist
这是我在编译时缺少这些依赖项时遇到的那种错误。
并且 Gradle 给了我以下关于 运行 时间依赖性的报告(来自 运行ning gradle dependencies
)我认为 Gradle 以某种方式管理这些:
compile - Compile classpath for source set 'main'.
\--- org.jdesktop:appframework:1.0.3
\--- org.jdesktop:swing-worker:1.1
…
runtime - Runtime classpath for source set 'main'.
\--- org.jdesktop:appframework:1.0.3
\--- org.jdesktop:swing-worker:1.1
…
最后知道是缺少运行time dependencies的问题后,我找到了几种提供方式,分享给大家。
第一个解决方案:链接到缓存
如 this Whosebug answer 所述 Gradle 在 $HOME/.gradle
中缓存依赖项,但它们的实际路径很棘手。答案描述了一个小的 Gradle 任务,它输出缓存中每个依赖项的完整路径(在本例中为 compile
配置,这正是我需要的):
task showMeCache << {
configurations.compile.each { println it }
}
就我而言 gradle showMeCache
报告:
$HOME/.gradle/caches/modules-2/files-2.1/org.jdesktop/appframework/1.0.3/338045feff6e61df237aafd11b6f3fe1a3b4e60e/appframework-1.0.3.jar
$HOME/.gradle/caches/modules-2/files-2.1/org.jdesktop/swing-worker/1.1/dc9f8d6f7236087924aad28fbec794a087dd1b3d/swing-worker-1.1.jar
这些是又长又讨厌的文件路径,但我能够构建一个 java
命令,该命令以 @chuchikaeschtli 建议的样式工作:
java \
-cp build/classes/main/\
:$HOME/.gradle/caches/modules-2/files-2.1/org.jdesktop/appframework/1.0.3/338045feff6e61df237aafd11b6f3fe1a3b4e60e/appframework-1.0.3.jar\
:$HOME/.gradle/caches/modules-2/files-2.1/org.jdesktop/swing-worker/1.1/dc9f8d6f7236087924aad28fbec794a087dd1b3d/swing-worker-1.1.jar \
demo.BasicSingleFrameApp
这行得通,但当然感觉不太“对”。但这有助于理解问题:这实际上是缺少依赖 jar 的问题。
方案二:同步依赖到build
目录
在 Using the Sync task of the Gradle User Guide 部分中,它明确使用了一个示例来描述手头问题的更好解决方案:
Here is an example which maintains a copy of the project's runtime dependencies in the build/libs directory.
task libs(type: Sync) {
from configurations.runtime
into "$buildDir/libs"
}
在 运行 使用 gradle libs
执行此任务后,我能够构建一个更简单的工作 java
命令:
java -cp build/classes/main/:build/libs/appframework-1.0.3.jar:build/libs/swing-worker-1.1.jar demo.BasicSingleFrameApp
请记住:默认情况下,这些依赖项并未同步到 build
目录中!
第三种解决方案:使用Gradle到运行应用程序
与Application PluginGradle本身提供了一个方便的解决方案运行ning一个应用程序。将这两行添加到我的 build.gradle
之后
apply plugin:'application'
mainClassName = 'demo.BasicSingleFrameApp'
我只需要 gradle run
就可以成功启动应用程序。迄今为止最简单的解决方案!
请注意,应用程序插件还提供了一个名为 installDist
的任务,该任务在 build/install
中创建了一个 运行 应用程序及其所有依赖项的可用分发,包括用于 UNIX 的启动脚本和 Windows 系统。这样做的好处是不需要 Gradle 来执行应用程序。
此外,如果您喜欢应用程序插件的 gradle run
任务,但担心 Gradle 在目标系统上是否可用,请查看 Gradle Wrapper。
第四种解决方案:创建 One-JAR、Fat Jar 或 Uber Jar
似乎存在 Gradle-only ways and Gradle plugins 可以帮助创建这些包含应用程序所需的所有依赖项的 jar。
在 gradle-one-jar-Plugin 的情况下,可以使用 java
命令启动应用程序,例如:
java -jar build/libs/YOUR_APP_NAME-standalone.jar
我正在尝试从 this article explaining the Swing Application Framework (JSR 296) with Gradle 编译代码示例 3,然后使用 java
命令从命令行将其编译为 运行。
我的目录布局如下所示:
├── build.gradle
└── src/
└── main/
└── java/
└── demo/
└── BasicSingleFrameApp.java
build.gradle
文件定义了对 appframework
:
apply plugin: 'java'
repositories {
mavenCentral()
}
dependencies {
compile 'org.jdesktop:appframework:1.0.3'
}
这是 BasicSingleFrameApp.java
文件,上面提到的文章示例的副本,由包声明增强:
package demo;
import org.jdesktop.application.*;
import javax.swing.*;
import java.awt.*;
public class BasicSingleFrameApp extends SingleFrameApplication {
JLabel label;
@Override
protected void startup() {
getMainFrame().setTitle("BasicSingleFrameApp");
label = new JLabel("Hello, world!");
label.setFont(new Font("SansSerif", Font.PLAIN, 22));
show(label);
}
public static void main(String[] args) {
Application.launch(BasicSingleFrameApp.class, args);
}
}
使用 gradle build
编译工作正常且没有错误。
但是当我尝试 运行 BasicSingleFrameApp
和
$ java -cp build/classes/main/ demo.BasicSingleFrameApp
我收到错误消息:
Error: Could not find or load main class demo.BasicSingleFrameApp
当我用简单的“Hello, world!”替换 BasicSingleFrameApp
class 时在没有依赖项的情况下打印 class,一切正常。
我很困惑,因为据我所知,我正确设置了 class 路径,但我不明白为什么找不到 main
方法(具有正确的签名)。
这是我的 Java 版本:
java version "1.8.0_20"
Java(TM) SE Runtime Environment (build 1.8.0_20-b26)
Java HotSpot(TM) 64-Bit Server VM (build 25.20-b23, mixed mode)
我正在 运行宁 Mac OS X Yosemite 10.10.2.
据我所知,您正在使用 java 启动应用程序,因此您必须告诉 java 在哪里可以找到您下载的 swing 应用程序框架 jar。所以命令应该看起来像
java -cp pathtojdektopjar/jdesktopjar.jar;build/classes/main/ demo.BasicSingleFrameApp
好的,所以@chuchikaeschtli 帮助我找到了问题的核心,即 Gradle 管理编译的依赖项并报告在 运行 时间内这样做,但更多的手动任务是需要在 运行 时间内使这些依赖项可用。
仍然让我感到困惑的是我收到的不直观的错误消息:
Error: Could not find or load main class demo.BasicSingleFrameApp
我本以为会在 运行 时出现与缺少依赖项有关的问题,然后报告
之类的错误error: package org.jdesktop.application does not exist
这是我在编译时缺少这些依赖项时遇到的那种错误。
并且 Gradle 给了我以下关于 运行 时间依赖性的报告(来自 运行ning gradle dependencies
)我认为 Gradle 以某种方式管理这些:
compile - Compile classpath for source set 'main'.
\--- org.jdesktop:appframework:1.0.3
\--- org.jdesktop:swing-worker:1.1
…
runtime - Runtime classpath for source set 'main'.
\--- org.jdesktop:appframework:1.0.3
\--- org.jdesktop:swing-worker:1.1
…
最后知道是缺少运行time dependencies的问题后,我找到了几种提供方式,分享给大家。
第一个解决方案:链接到缓存
如 this Whosebug answer 所述 Gradle 在 $HOME/.gradle
中缓存依赖项,但它们的实际路径很棘手。答案描述了一个小的 Gradle 任务,它输出缓存中每个依赖项的完整路径(在本例中为 compile
配置,这正是我需要的):
task showMeCache << {
configurations.compile.each { println it }
}
就我而言 gradle showMeCache
报告:
$HOME/.gradle/caches/modules-2/files-2.1/org.jdesktop/appframework/1.0.3/338045feff6e61df237aafd11b6f3fe1a3b4e60e/appframework-1.0.3.jar
$HOME/.gradle/caches/modules-2/files-2.1/org.jdesktop/swing-worker/1.1/dc9f8d6f7236087924aad28fbec794a087dd1b3d/swing-worker-1.1.jar
这些是又长又讨厌的文件路径,但我能够构建一个 java
命令,该命令以 @chuchikaeschtli 建议的样式工作:
java \
-cp build/classes/main/\
:$HOME/.gradle/caches/modules-2/files-2.1/org.jdesktop/appframework/1.0.3/338045feff6e61df237aafd11b6f3fe1a3b4e60e/appframework-1.0.3.jar\
:$HOME/.gradle/caches/modules-2/files-2.1/org.jdesktop/swing-worker/1.1/dc9f8d6f7236087924aad28fbec794a087dd1b3d/swing-worker-1.1.jar \
demo.BasicSingleFrameApp
这行得通,但当然感觉不太“对”。但这有助于理解问题:这实际上是缺少依赖 jar 的问题。
方案二:同步依赖到build
目录
在 Using the Sync task of the Gradle User Guide 部分中,它明确使用了一个示例来描述手头问题的更好解决方案:
Here is an example which maintains a copy of the project's runtime dependencies in the build/libs directory.
task libs(type: Sync) {
from configurations.runtime
into "$buildDir/libs"
}
在 运行 使用 gradle libs
执行此任务后,我能够构建一个更简单的工作 java
命令:
java -cp build/classes/main/:build/libs/appframework-1.0.3.jar:build/libs/swing-worker-1.1.jar demo.BasicSingleFrameApp
请记住:默认情况下,这些依赖项并未同步到 build
目录中!
第三种解决方案:使用Gradle到运行应用程序
与Application PluginGradle本身提供了一个方便的解决方案运行ning一个应用程序。将这两行添加到我的 build.gradle
apply plugin:'application'
mainClassName = 'demo.BasicSingleFrameApp'
我只需要 gradle run
就可以成功启动应用程序。迄今为止最简单的解决方案!
请注意,应用程序插件还提供了一个名为 installDist
的任务,该任务在 build/install
中创建了一个 运行 应用程序及其所有依赖项的可用分发,包括用于 UNIX 的启动脚本和 Windows 系统。这样做的好处是不需要 Gradle 来执行应用程序。
此外,如果您喜欢应用程序插件的 gradle run
任务,但担心 Gradle 在目标系统上是否可用,请查看 Gradle Wrapper。
第四种解决方案:创建 One-JAR、Fat Jar 或 Uber Jar
似乎存在 Gradle-only ways and Gradle plugins 可以帮助创建这些包含应用程序所需的所有依赖项的 jar。
在 gradle-one-jar-Plugin 的情况下,可以使用 java
命令启动应用程序,例如:
java -jar build/libs/YOUR_APP_NAME-standalone.jar