在构建Java9模块的Gradle项目中,资源文件放在哪里?

在构建Java9模块的Gradle项目中,资源文件放在哪里?,java,gradle,embedded-resource,java-9,java-module,Java,Gradle,Embedded Resource,Java 9,Java Module,从IDEA 2018.2.1开始,IDE开始错误突出显示包“非 在模块图中,“来自已模块化的依赖项”。我在我的项目中添加了一个module info.java文件,并添加了 requisite需要语句,但我现在无法访问 我的src/main/resources目录中的资源文件 (有关完整示例,请参见。) 当我使用/gradlew run或/gradlew installDist+生成 包装器脚本,我能够读取资源文件,但当我运行 来自IDE的应用程序,我不是 我提交了一份 有了JetBrains,

从IDEA 2018.2.1开始,IDE开始错误突出显示包“非 在模块图中,“来自已模块化的依赖项”。我在我的项目中添加了一个
module info.java
文件,并添加了 requisite
需要
语句,但我现在无法访问 我的
src/main/resources
目录中的资源文件

(有关完整示例,请参见。)

当我使用
/gradlew run
/gradlew installDist
+生成 包装器脚本,我能够读取资源文件,但当我运行 来自IDE的应用程序,我不是

我提交了一份 有了JetBrains,我学到的是这个想法就是使用这个模块 默认情况下,Gradle使用的是类路径。加入 在我的
build.gradle
的下面一个模块中,我能够获得gradle 到…无法读取任何资源文件

run {
    inputs.property("moduleName", moduleName)
    doFirst {
        jvmArgs = [
                '--module-path', classpath.asPath,
                '--module', "$moduleName/$mainClassName"
        ]
        classpath = files()
    }
}
我试着导出我感兴趣的资源目录 “package”,编译时生成失败,原因是:

错误:包为空或不存在:mydir

使用
打开
而不是
导出
会出现相同的错误,尽管降级了 警告

我甚至试着移动
src/main/java
下的
mydir
资源目录, 但这会产生相同的错误/警告,并导致 未将资源复制到
生成
目录

Java 9中的资源应该放在哪里?我如何访问它们


注意:在继续讨论之后,我对这个问题进行了大量编辑 研究这个问题。在最初的问题中,我也试图 了解如何在资源目录中列出文件,但在 在调查过程中,我确定这是一个骗局-- 首先,因为只有当 正在从
文件中读取资源://
URL(甚至可能不是这样), 第二,因为普通文件也不起作用,所以很明显 问题是一般的资源文件,而不是具体的资源文件 目录


解决方案:

根据,我在build.gradle中添加了以下内容:

// at compile time, put resources in same directories as classes
sourceSets {
  main.output.resourcesDir = main.java.outputDir
}

// at compile time, include resources in module
compileJava {
  inputs.property("moduleName", moduleName)
  doFirst {
    options.compilerArgs = [
      '--module-path', classpath.asPath,
      '--patch-module', "$moduleName=" 
        + files(sourceSets.main.resources.srcDirs).asPath,
      '--module-version', "$moduleVersion"
    ]
    classpath = files()
  }
}

// at run time, make Gradle use the module path
run {
  inputs.property("moduleName", moduleName)
  doFirst {
    jvmArgs = [
      '--module-path', classpath.asPath,
      '--module', "$moduleName/$mainClassName"
    ]
    classpath = files()
  }
}
旁注:有趣的是,如果我不继续添加Slaw的代码,使
运行
任务对JAR执行,尝试现在读取运行任务中的资源目录
InputStream
,而不是提供文件列表。(相对于JAR,它只得到一个空的
InputStream

更新(2020年3月25日):在适当的JPMS支持方面取得了重大进展。Gradle 6.4的夜间构建现在包括使用Java9模块进行本地开发的选项。看

更新(2020年9月29日):自Gradle 6.4(截至本次更新的当前版本为6.6.1)以来,您现在可以在Gradle项目中本机支持JPMS模块,但您必须明确激活此功能:

java{
模块化.inferModulePath.set(true)
}
有关更多信息,请参阅Gradle's,它还链接到其他各种相关文档


Gradle和java9模块支持 不幸的是,从6.0.1版开始,Gradle仍然没有对Java9模块的一流支持,正如指南所示

Java9最令人兴奋的特性之一是它支持开发和部署模块化Java软件。Gradle还没有对Java9模块的一流支持

一些,比如,试图增加支持。本指南将在开发时更新更多关于如何使用内置Gradle支持的信息

注意:本指南过去更为广泛,并提供了如何“手动”自定义现有任务的示例。但是,它后来改为上面的内容,建议使用至少提供一些Java9支持的第三方插件。其中一些社区插件似乎不仅仅提供模块支持,例如支持使用Gradle提供的
jlink
工具

Gradle项目有一个“epic”,据说它跟踪Java9模块支持:


问题 找不到资源文件的原因是,默认情况下,Gradle会在不同的目录中输出已编译的类和已处理的资源。它看起来像这样:

构建/
|--班级/
|--资源/
classes
目录是放置
module info.class
文件的地方。这会导致模块系统出现问题,因为从技术上讲,
资源
目录下的文件不包括在
目录下的模块中。当使用类路径而不是modulepath时,这不是问题,因为模块系统将整个类路径视为一个巨大的模块(即所谓的未命名模块)

如果为仅限资源的包添加
opens
指令,则在运行时会出现错误。错误的原因是由于前面提到的目录布局,模块中不存在包。您在编译时收到警告的原因基本相同;该模块存在于
src/main/java
中,
src/main/resources
下的资源文件在技术上不包括在该模块中

注意:我所说的“仅资源包”是指包含资源但没有任何资源具有
.java
.class
扩展名的包

当然,如果资源仅可供模块本身访问,则无需添加
opens
指令。当其他模块需要访问资源时,您只需要为包含资源的包添加此类指令,因为模块中的资源受限制

资源
opens io.fouad.packageone to moduletwo.name;
A.class.getResource("/io/fouad/packageone/logging.properties");
public static URL getLoggingConfigFileAsResource()
{
    return A.class.getResource("/io/fouad/packageone/logging.properties");
}