我正在尝试使用this article explaining the Swing Application Framework (JSR 296)从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
类时,一切正常。
我很困惑,因为根据我的理解,我正确设置了类路径,但我不明白为什么找不到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。
答案 0 :(得分:4)
好的,所以@chuchikaeschtli帮助我解决了问题的核心,即Gradle管理用于编译的依赖项并报告为运行时执行此操作,但是需要更多的手动任务来使这些依赖项在运行时可用。
让我感到困惑的是我收到的不直观的错误信息:
Error: Could not find or load main class demo.BasicSingleFrameApp
我原本预料到一个问题与运行时缺少依赖关系有关,以报告错误,如
error: package org.jdesktop.application does not exist
这是在编译时缺少这些依赖项时遇到的错误。
正如Gradle给我的关于运行时依赖关系的以下报告(通过运行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
…
最后,在知道缺少运行时依赖性的问题之后,我找到了几种提供它们的方法,我将分享这些方法。
第一个解决方案:链接到缓存
如this Stackoverflow 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
这些是冗长而令人讨厌的文件路径,但是我能够构建一个以{chuchikaeschtli建议的方式工作的java
命令:
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
这有效,但当然这感觉不是很“正确”。但它有助于理解这个问题:这实际上是缺少依赖性罐子的问题。
第二个解决方案:将依赖项同步到build
目录
在Using the Sync task of the Gradle User Guide部分中,它明确使用了一个示例来描述解决问题的更好方法:
这是一个在build / libs目录中维护项目运行时依赖项副本的示例。
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 Plugin Gradle本身为运行应用程序提供了方便的解决方案。将这两行添加到build.gradle
apply plugin:'application'
mainClassName = 'demo.BasicSingleFrameApp'
我只用gradle run
成功启动了应用程序。迄今为止最简单的解决方案!
请注意,应用程序插件还提供了一个名为installDist
的任务,该任务在build/install
内创建了应用程序及其所有依赖项的可运行分发,并包含UNIX和Windows系统的启动脚本。这样做的好处是不需要Gradle来执行应用程序。
此外,如果您喜欢Application Plugin的gradle run
任务,但担心Gradle在目标系统上是否可用,请查看Gradle Wrapper。
第四个解决方案:创建One-JAR,Fat Jar或Uber Jar
似乎存在Gradle-only ways和Gradle plugins有助于创建这些包含应用程序所需的所有依赖项的jar。
在gradle-one-jar-Plugin的情况下,可以使用java
命令启动应用程序,如:
java -jar build/libs/YOUR_APP_NAME-standalone.jar
答案 1 :(得分:0)
从我得到的是你刚刚使用java启动应用程序所以你必须告诉java在哪里找到你下载的swing应用程序框架jar。所以命令应该看起来像
java -cp pathtojdektopjar/jdesktopjar.jar;build/classes/main/ demo.BasicSingleFrameApp