为什么添加模块信息后Java无法读取同一个资源文件?
Why Java cannot read same resource file when module-info is added?
有一个具有标准 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/abc/cde.txt"
(编译后的代码)。
添加文件src/main/java/module-info.java
后情况发生变化:程序找不到文件并抛出in branch (input == null)
.
如何以旧方式从“资源”文件夹中读取文件并在资源文件夹中同时拥有:java-模块和资源?我想避免在任何地方添加前缀 "src/main/resources"
。
你可能想要这个:
InputStream input = Main.class.getResourceAsStream("/abc/cde.txt");
当您添加模块-info.java 时,您的 class 被 Java 视为 module。
模块的封装限制超出了普通旧 classpath 的限制。要访问模块中的资源,其他代码必须通过该模块,这将检查调用代码的模块是否有权读取这些资源。
ClassLoader.getResourceAsStream will only read resources from explicitly opened modules:
Additionally … this method will only find resources in packages of named modules when the package is opened unconditionally.
但是Class.getResource and Class.getResourceAsStream只依赖class所属的模块,没有那个额外的限制
应始终使用 Class.getResource 或 Class.getResourceAsStream。应避免使用 ClassLoader 等价物。
Class 方法和 ClassLoader 方法之间有一个重要的区别:Class 方法将参数视为相对于 class 的包, 除非参数以斜线开头 (/
).
除了封装限制,给定一个名为com.example.MyApplication的class,这两行是等价的:
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* 方法。
有一个具有标准 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/abc/cde.txt"
(编译后的代码)。
添加文件src/main/java/module-info.java
后情况发生变化:程序找不到文件并抛出in branch (input == null)
.
如何以旧方式从“资源”文件夹中读取文件并在资源文件夹中同时拥有:java-模块和资源?我想避免在任何地方添加前缀 "src/main/resources"
。
你可能想要这个:
InputStream input = Main.class.getResourceAsStream("/abc/cde.txt");
当您添加模块-info.java 时,您的 class 被 Java 视为 module。
模块的封装限制超出了普通旧 classpath 的限制。要访问模块中的资源,其他代码必须通过该模块,这将检查调用代码的模块是否有权读取这些资源。
ClassLoader.getResourceAsStream will only read resources from explicitly opened modules:
Additionally … this method will only find resources in packages of named modules when the package is opened unconditionally.
但是Class.getResource and Class.getResourceAsStream只依赖class所属的模块,没有那个额外的限制
应始终使用 Class.getResource 或 Class.getResourceAsStream。应避免使用 ClassLoader 等价物。
Class 方法和 ClassLoader 方法之间有一个重要的区别:Class 方法将参数视为相对于 class 的包, 除非参数以斜线开头 (/
).
除了封装限制,给定一个名为com.example.MyApplication的class,这两行是等价的:
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* 方法。