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

如何在gradle中导出可执行jar,这个jar可以运行,因为它包含引用库

郭元凯
2023-03-14

如何在gradle中导出可执行jar,并且这个jar可以运行,因为它包含引用库。

建筑格拉德尔

apply plugin: 'java'

manifest.mainAttributes("Main-Class" : "com.botwave.analysis.LogAnalyzer")

repositories {
    mavenCentral()
}

dependencies {
    compile (
        'commons-codec:commons-codec:1.6',
        'commons-logging:commons-logging:1.1.1',
        'org.apache.httpcomponents:httpclient:4.2.1',
        'org.apache.httpcomponents:httpclient:4.2.1',
        'org.apache.httpcomponents:httpcore:4.2.1',
        'org.apache.httpcomponents:httpmime:4.2.1',
        'ch.qos.logback:logback-classic:1.0.6',
        'ch.qos.logback:logback-core:1.0.6',
        'org.slf4j:slf4j-api:1.6.0',
        'junit:junit:4.+'
    )
}

跑步后:gradle build

它创建build文件夹,我在build/libs/XXX中运行jar。震击器:

java-jar构建/libs/XXX. jar

这里有一个执行说明:

Exception in thread "main" java.lang.NoClassDefFoundError: ch/qos/logback/core/joran/spi/JoranException

我如何使用参考库运行它?

共有3个答案

周作人
2023-03-14

>

  • 将以下内容添加到您的构建中。格雷德尔:

    apply plugin: 'application'
    
    mainClassName = 'org.example.app.MainClass'
    
    jar {
        manifest {
            attributes 'Main-Class': mainClassName,
                       'Class-Path': configurations.runtime.files.collect {"$it.name"}.join(' ')
        }
    }
    

    我建议将应用程序版本添加到您的构建中。gradle也是,但不是必需的。如果这样做,构建的jar名称将是

    注意:我使用的是gradle 2.5

    为了创建一个自包含的可执行jar,您可以简单地使用它运行:

    java -jar appname.jar
    

    您将需要:

    1. jar中包含一个指向应用程序主类的清单文件
    2. 所有依赖项(应用程序外部JAR中的类)都要以某种方式包含或访问
    3. 您的清单文件包含正确的类路径

    正如其他一些答案所指出的,您可以使用一些第三方插件来实现这一点,例如影子或一个罐子。

    我尝试了shadow,但不喜欢我的所有依赖项及其资源与我的应用程序代码一起直接转储到构建的jar中。我还希望尽量减少使用外部插件。

    另一种选择是使用上面@erdi回答的gradle应用程序插件。运行gradle build将为您构建一个jar,并将其与您的所有依赖项很好地捆绑在一个zip/tar文件中。您也可以只运行gradle installDist来跳过压缩。

    然而,正如@jeremyjjbrown在那里的评论中所写的那样,插件本身并没有创建可执行的jar。它创建了一个jar和一个脚本,用于构造类路径并执行命令来运行应用程序的主类。您将无法运行java-jar appname。jar

    要两全其美,请按照上面的步骤将jar与所有依赖项一起创建为单独的jar,并将正确的值添加到MANIEST。

  • 和柏
    2023-03-14

    希望这能帮助一些人(不幸的是,我花了很长时间试图找到解决方案)。这是一个为我创建可执行JAR的解决方案。我将Jetty嵌入到主要方法中,具体来说是Jetty 9,并使用Gradle 2.1。

    将以下代码包含到您的build.gradle文件中(如果一个子项目是需要构建jar的“主”项目,那么将其添加到应该像这个项目一样开始的子项目中(':') { 在依赖项之后的某处插入代码。}。

    此外,您需要添加插件java才能正常工作:应用插件:'java'。

    我的jar任务如下所示:

    apply plugin: 'java'
    
    jar {
    
        archiveName = "yourjar.jar"
    
        from {
    
            configurations.runtime.collect {
                it.isDirectory() ? it : zipTree(it)
            }
    
            configurations.compile.collect {
                it.isDirectory() ? it : zipTree(it)
            }
        }
    
        manifest {
            attributes 'Main-Class': 'your.package.name.Mainclassname'
        }
    
        exclude 'META-INF/*.RSA', 'META-INF/*.SF','META-INF/*.DSA'
    }
    

    然后您可以通过命令行执行yourjar.jar:

    java -jar yourjar.jar
    

    META-INF/。RSA、META-INF/。SF和META-INF/*。必须排除DSA才能使其工作。否则会抛出SecurityException。

    问题似乎在于嵌入式Jetty,因为Jetty迁移到Eclipse,现在正在对其jar进行签名,我读到,当其他未签名的jar想要加载签名的jar时,这个问题就会出现。如果我在这方面错了,请随时教育我,这正是我所读到的。

    项目依赖的JAR在依赖项中定义如下:

    dependencies {
    
        // add the subprojects / modules that this depends on
        compile project(':subproject-1')
        compile project(':subproject-2')
    
        compile group: 'org.eclipse.jetty', name: 'jetty-server', version: '9.2.6.v20141205'
        compile group: 'org.eclipse.jetty', name: 'jetty-servlet', version: '9.2.6.v20141205'
        compile group: 'org.eclipse.jetty', name: 'jetty-http', version: '9.2.6.v20141205'
    
    }
    

    编辑:在之前,而不是仅仅

    configurations.runtime.collect{...}
    

    我有过

    configurations.runtime.asFileTree.files.collect{...}
    

    这在clean build中的一个较大项目中导致了奇怪的行为。在第一次执行gradle clean build之后运行jar时(在手动清理构建目录之后),它会抛出NoClassDefFoundException(在我们有许多子项目的项目中),但在第二次执行gradle clean build之后运行jar(不手动清空构建目录),出于某种原因,它具有所有依赖项。如果是asFileTree,则不会发生这种情况。文件被遗漏了。

    另外我应该注意的是,所有编译依赖项都包含在运行时中,但并非所有运行时都包含在编译中。所以如果你只是使用编译

            configurations.compile.collect {
                it.isDirectory() ? it : zipTree(it)
            }
    

    然后请务必记住,如果抛出NoClassDefFoundException,则在运行时找不到某些类,这意味着您还应该包含以下内容:

            configurations.runtime.collect {
                it.isDirectory() ? it : zipTree(it)
            }
    
    仇浩旷
    2023-03-14

    您可以使用Gradle应用程序插件实现它

     类似资料:
    • 我需要从eclipse IDE导出一个可运行的jar。我给出的启动配置有库jar中的main类。 在eclipse中,我可以运行该程序。但我想将项目导出为可运行的JAR。但收到错误“无法从启动配置中找到main method”。 如何从库jar导出具有main方法的jar? 注意:如果我用其他类导出jar,并将主类名更改为库jar中存在的类名,那么它就可以工作。

    • 本文向大家介绍Eclipse 导出可执行Java工程/可执行Jar文件(包含第三方Jar包),包括了Eclipse 导出可执行Java工程/可执行Jar文件(包含第三方Jar包)的使用技巧和注意事项,需要的朋友参考一下 Eclipse导出可执行Java工程/可执行Jar文件(包含第三方Jar包) 师兄部署了新的虚拟机,新学期大搞起来!之前由于爬虫代码不稳定,所以一直都是直接用Eclipse运行,然

    • 问题内容: 我在将当前项目提取到可执行jar文件时遇到问题。当我在日食中按下运行按钮时,一切正常,但是当我这样做时 然后启动.jar文件;我唯一得到的是带有灰色画布的窗口。它应该启动我编写的游戏(spaceInvaders)。 这是我上载项目的github的链接。我真的不知道错误在哪里,在哪里看。在我的代码中?在我安装的JRE / JDK中?创建罐子时我做错什么了吗? 请帮忙 -。- 问题答案:

    • 问题内容: 我创建了一个使用SQLite作为本地数据库的Swing应用程序。数据库文件位于项目的根目录中。 该应用程序在Eclipse上运行良好,但是当我运行打包的可执行文件Jar时,出现以下错误: 这意味着数据库不可访问。当我检查生成的JAR文件的内容时,数据库文件不再存在。 在代码中,我将数据库链接如下: 我的问题是,如何在可执行的Jar中包含SQLite数据库? 编辑 当我将数据库文件放在源

    • 我创建了一个Swing应用程序,它使用SQLite作为本地数据库。数据库文件位于项目的根目录中。 该应用程序在Eclipse上运行良好,但当我运行打包的可执行Jar时,会出现以下错误: 这意味着无法访问数据库。当我检查结果JAR文件的内容时,数据库文件已经不在了。 在代码中,我将数据库链接如下: 我的问题是,如何在可执行Jar中包含SQLite数据库? 编辑 当我把DB文件放在源代码文件夹并将路径