当前位置: 首页 > 知识库问答 >
问题:

通过Java命令运行带依赖项的Gradle编译Java应用程序

柴彬
2023-03-14

我试图编译本文中的代码示例3,解释使用Gradle的Swing应用程序框架(JSR 296),并使用java命令从命令行运行它。

我的目录布局如下所示:

├── build.gradle
└── src/
    └── main/
        └── java/
            └── demo/
                └── BasicSingleFrameApp.java

构建。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编译工作正常,没有错误。

但是当我尝试使用

$ 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。

共有2个答案

白灿
2023-03-14

我得到的信息是,您只是使用java启动应用程序,所以您必须告诉java在哪里可以找到您下载的swing应用程序框架jar。所以命令应该类似于

java -cp pathtojdektopjar/jdesktopjar.jar;build/classes/main/ demo.BasicSingleFrameApp
和选
2023-03-14

好的,所以@chuchikaeschtli帮助我找到了问题的核心,即Gradle管理编译的依赖项和运行时的报告,但需要更多的手动任务才能使这些依赖项在运行时可用。

仍然让我困惑的是,我收到了一条不直观的错误消息

Error: Could not find or load main class demo.BasicSingleFrameApp

我本以为会有一个与运行时缺少依赖项有关的问题报告如下错误

error: package org.jdesktop.application does not exist

当这些依赖项在编译时丢失时,我会遇到这种错误。

当Gradle给我关于运行时依赖关系的以下报告时(通过运行Gradle依赖关系),我认为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
…

最后,在知道缺少运行时依赖关系是一个问题后,我找到了几种提供它们的方法,我将与大家分享。

第一个解决方案:链接到缓存

如本Stackoverflow答案中所述,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

这是有效的,但当然这感觉不太“正确”。但它有助于理解问题:这实际上是一个缺少依赖罐的问题。

第二种解决方案:将依赖项同步到构建目录

在Gradle用户指南的使用同步任务部分中,它明确使用了一个示例来描述手头问题的更好解决方案:

这是一个在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

请记住:默认情况下,这些依赖项尚未同步到构建目录中!

第三种解决方案:使用Gradle运行应用程序

使用Application Plugin Gradle本身为运行应用程序提供了一个方便的解决方案。将这两行添加到我的build.gradle

apply plugin:'application'

mainClassName = 'demo.BasicSingleFrameApp'

我只需运行gradle,就可以成功地启动应用程序。迄今为止最简单的解决方案!

请注意,应用程序插件还提供了一个名为install Dist的任务,该任务在build/install中创建了应用程序及其所有依赖项的可运行发行版,并包含UNIX和Windows系统的启动脚本。这具有执行应用程序不需要Gradle的优点。

此外,如果您喜欢应用程序插件的gradle run任务,但担心gradle在目标系统上是否可用,请查看gradle包装器。

第四种解决方案:创建一个单罐、胖罐或优步罐

似乎存在一些只有Gradle的方法和Gradle插件来帮助创建这些JAR,其中包括应用程序所需的所有依赖项。

在gradle-one-jar-Plugin的情况下,应用程序可以使用java命令启动,例如:

java -jar build/libs/YOUR_APP_NAME-standalone.jar
 类似资料:
  • 我需要使用WebSocket,但是我们使用的旧版本的PHP不支持它们。我决定尝试一个Java的WebSocket服务器。我已经在Android Studio中编写了一些Android应用程序,所以我熟悉Java的基本语法,但是几乎没有手动编译和运行java的经验。 我希望服务器是一个单一的文件,我可以从命令行运行一次,然后忘记它。为此,我决定使用这个库,在示例中包含一个Javascript聊天应用

  • 我正在使用mongodb和Spring Boot。最近,我的mongodb升级到了3.0版本。 我对Spring使用以下Gradle依赖项: 如果我查看maven存储库中的gradle:,我会看到以下内容(http://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-mongodb/1.2.6

  • 问题内容: 我发现了几个用于通过Java类运行cmd命令的代码段,但我无法理解。 这是打开cmd的代码 我找到了一些其他链接来添加其他命令,例如cd http://www.coderanch.com/t/109753/Linux-UNIX/exec-command-cd-command-java 如何使用Java打开命令提示符并插入命令? 谁能帮助我了解如何CD目录,例如: 然后在该目录上运行其他

  • 我找到了几个通过Java类运行cmd命令的代码片段,但我无法理解。 这是打开命令的代码 我还找到了一些添加其他命令的链接,比如cdhttp://www.coderanch.com/t/109753/Linux-UNIX/exec-command-cd-command-java 如何使用Java打开命令提示符并插入命令? 有人能帮我了解如何cd目录,例如: 然后在该目录上运行其他命令?

  • 我有一个包含以下文件的Java项目: C:\MyProject\myPackage\MyTests.class C:\MyProject\lib\junit-platform-console-standalone-1.5.2.jar C:\MyProject\lib\other-library.jar MyTests 文件是使用 IDE 编译的,该 IDE 具有 junit-platform-co

  • 我正在尝试使用ProcessBuild运行cmd语句。 但是,我只能打开cmd。exe 那么如何编写此语句通过java运行cmd命令??我得到了错误,因为语句由"*"组成。如何编辑ProcessBuilder以便我可以运行语句?非常感谢