为什么java在添加模块信息时不能读取相同的资源文件?

3df52oht  于 2021-08-20  发布在  Java
关注(0)|答案(1)|浏览(461)

有一个具有标准maven文件夹结构的简单java项目。

src
  main
    java
      mypackage
        Main.java
    resource
      abc
        cde.txt

main.java(样板文件省略)

var path = "abc/cde.txt";
InputStream input = Thread.currentThread().getContextClassLoader().getResourceAsStream(path);

if (input == null) {
    throw new IllegalStateException("Resource not found");
} else {
   // read from input
}

这段代码工作正常,可以从绝对路径读取文件 "%project_root%/target/classes//cde.txt" (编译代码)。
添加文件后 src/main/java/module-info.java 情况发生了变化:程序找不到文件并抛出 in branch (input == null) .
如何以旧的方式从“资源”文件夹中读取文件,并在资源文件夹中同时包含java模块和资源?我希望避免添加前缀 "src/main/resources" 到处都是。

agyaoht7

agyaoht71#

你可能想要这个:

InputStream input = Main.class.getResourceAsStream("/abc/cde.txt");

当您添加module-info.java时,您的类被java视为一个模块。
模块的封装限制超出了普通旧类路径的限制。要访问模块中的资源,其他代码必须通过该模块,这将检查调用代码的模块是否具有读取这些资源的权限。
classloader.getresourceasstream将仅从显式打开的模块中读取资源:
此外,当包被无条件打开时,此方法将仅在命名模块的包中查找资源。
但是class.getresource和class.getresourceasstream只依赖于类所属的模块,没有额外的限制。
应该始终使用class.getresource或class.getresourceasstream。应该避免使用类加载器等价物。
类方法和类装入器方法之间有一个重要区别:类方法将参数视为相对于类的包,除非参数以斜杠开头( / ).
除了封装限制外,给定一个名为com.example.myapplication的类,这两行是等效的:

MyApplication.class.getResource("data.txt")
MyApplication.class.getClassLoader().getResource("com/example/data.txt")

这些是等效的:

MyApplication.class.getResource("/data.txt")
MyApplication.class.getClassLoader().getResource("data.txt")

同样,它们仅在资源路径方面是等价的;模块化封装限制是不同的。始终使用class.getresource方法,避免使用classloader.getresource方法。

相关问题