如何从 Gradle 中的 JAR 中排除资源并通过 IntelliJ 运行

Dan*_*mas 7 java resources build gradle

我最近开始从事一个已有 7 年多历史的项目,该项目使用 Ant/Ivy进行依赖和构建管理。我的任务是将其转换为 Gradle,但结构有点不传统:

|- projectRoot
  |- folderA
  |- folderB
  |- projectX
    |- conf
    | |- file1.txt
    |
    |- core
    |  |- src
    |  | |- App.java
    |  |
    |  |- test
    |    |- AppTest.java
    |
    |- res
    | |- file2.txt
    |
    |- ivybuild.xml
    |- ivysettings.xml
Run Code Online (Sandbox Code Playgroud)

Ivy 构建过程相当简单,生成的 dist 文件夹如下所示:

|- dist
  |- proj.jar
  |- lib
  |  |- dep1.jar
  |  |- dep2.jar
  |
  |- conf
  |  |- file1.txt
  |- res
     |- file2.txt
Run Code Online (Sandbox Code Playgroud)

生成的 JAR 中不会内置任何资源,因为某些配置是在部署期间从单独的存储库应用的,因此资源必须保留在 JAR 外部。

我正在努力寻找一种方法来实现这一目标,同时还让 IDE (Intellij IDEA) 在调试和运行测试期间成功找到资源。

sourceSets {
    main {
        java {
            srcDir 'core/src'
        }
        resources {
            srcDir 'conf'
            srcDir 'res'
        }
    }
    test {
        java {
            srcDir 'core/test'
        }
    }
}
processResources {
    from 'conf' into 'lib/conf'
    from 'res' into 'lib/res'
}
startScripts {
    classpath += files('conf')
    classpath += files('res')
}
Run Code Online (Sandbox Code Playgroud)

通过上述内容,我能够成功运行/测试项目,因为“conf”和“res”中的所有文件都被复制到“build/resources/main”中,这允许调试和测试找到它们。它将两个资源目录复制到输出 lib 文件夹,并将它们添加到运行脚本中的类路径中。

除了资源仍被复制到构建的 JAR 中之外,上述方法均有效。这些会覆盖外部文件夹配置,因此不会起作用。

jar {
    processResources {
        exclude("*")
    }
}
Run Code Online (Sandbox Code Playgroud)

如果我现在运行,assemble那么构建的项目正是我想要的,但是 IDE 现在无法成功运行调试器或测试,因为它无法找到下面丢失的文件build/resources/main

我也尝试过使用idea插件来设置资源路径,但没有成功。

有办法吗?

Dan*_*mas 8

使用 Gradle 从 JAR 中排除资源

例子 build.gradle

plugins {
    id 'java'
    id 'application'
}

// Project specifics
version '1.0-SNAPSHOT'
group 'com.example'

sourceCompatibility = 1.8
project.mainClassName = "core.ExampleApp"

dependencies {
    testCompile 'junit:junit:4.12'
}

// Define the project source paths
sourceSets {
    main.java {
        srcDir 'core/src'
    }
    test.java {
        srcDir 'core/test'
    }
}

// Exclude all resources from the jar
jar {
    processResources.exclude('*')
}

// Allows the 'test' task to see the directories on the classpath
test {
    classpath += files('conf')
    classpath += files('res')
}

// Allows the 'run' task to see the directories on the classpath
run {
    classpath += files('conf')
    classpath += files('res')
}

// Adds the directories to classpath in the start scripts
// They will have '$APP_DIR/lib/' prepended so they need to be copied into 'dist/lib/'
startScripts {
    run {
        classpath += files('conf')
        classpath += files('res')
    }
}

// Copy 'conf' and 'res' into the 'dist/lib' directory
distributions {
    main {
        contents {
            from('conf').into("lib/conf")
            from('res').into("lib/res")
        }
    }
}

Run Code Online (Sandbox Code Playgroud)
  • 期间发现资源gradle run
  • 期间发现资源gradle test
  • 构建的JAR不包含资源
  • 资源复制到example.zip/lib/conf&.../lib/res
  • 资源内容添加到生成的构建脚本中的类路径中
  • 通过 IntelliJ UI 运行测试确实有效(right click -> run tests例如)

  • 通过 IntelliJ UI 运行不起作用(right click -> run main()例如)

解决

  • IntelliJ Gradle 插件允许right click -> runright click -> debug
  • 上面添加了 IntelliJ 运行面板的配置作为一个不错的替代品


小智 8

仅供参考:作为一个 gradle 新手,我最近在尝试从 jar 中排除一些 src/main/resources 文件时遇到了这个问题

// Exclude all resources from the jar
jar {
    processResources.exclude('*')
}
Run Code Online (Sandbox Code Playgroud)

实际上不仅仅是从 jar 中排除 - 它完全从构建中排除,因为它们不存在于 build/resources/ 中;所以可能会影响你的测试等。


dak*_*aka 6

在 Kotlin DSL 中

tasks.jar.configure {
    exclude("**/node_modules/")
    exclude("web/package*.json")
    exclude("web/*.config.js")
    archiveFileName.set("my.jar")
    ...
}
Run Code Online (Sandbox Code Playgroud)