在类路径中访问资源有两种主要方式,通过Class 对象和通过Classloader,通过获取getResourceAsStream。
最终,实现资源查找的精确规则取决于类加载器。但大部分都明确规定。按名称查找资源。
资源名称是一个以“/”分隔的路径名,用于标识该资源。
而且,在探索classpath的时候,搜索顺序也一目了然
此方法将首先在父类加载器中搜索资源;如果 parent 为 null,则搜索虚拟机内置的类加载器的路径。如果失败,此方法将调用 {@link #findResource(String)} 来查找资源。
findResource 是依赖于实现的部分。然而,大多数 Java 类加载器是某种URLClassLoaders,它们的实现知道如何探索类路径条目(在文件系统上或在 JAR 文件内部 - 甚至是远程文件)以将名称解析为所述条目中的相对或绝对路径.
因此,简而言之:您使用getResourceByName 来探索您的类路径,通过类路径中的相对或绝对路径查找文件。
Class#getResourceAsStream 和ClassLoader#getResourceAsStream 之间的区别在于Class 版本将相对路径解释为相对于Class 的包,而ClassLoader 版本将从类路径的根目录开始。
所以...鉴于以下项目结构:
src
name
gpi
file.txt
Test.java
这个 Test.java 有效:
public static void main(String[] args) throws IOException {
// relative path from this class
InputStream is = Test.class.getResourceAsStream("file.txt");
byte[] content = new byte[4096];
int length = is.read(content);
System.out.println(new String(content, 0, length));
// relative path from the root of the classpath
is = Test.class.getClassLoader().getResourceAsStream("name/gpi/file.txt");
content = new byte[4096];
length = is.read(content);
System.out.println(new String(content, 0, length));
}
注意文档中的细节,因为
// This works : on the class object, absolute path are treated as "root of the classpath"
InputStream is = Test.class.getResourceAsStream("/name/gpi/file.txt");
//This does not work, because this looks actually at the root of the file system
InputStream is = Test.class.getClassLoader().getResourceAsStream("/name/gpi/file.txt");
如果您尝试使用此处列出的组合,但实际上并没有,那么您要么有一个“时髦”的类加载器(这绝对不应该发生在一个简单的项目中),要么是您的编译器/打包器设置(maven 或eclipse 或其他) 的设置方式是从编译/打包结果 (JAR) 中丢弃您的 JKS 文件。
在一般的maven项目中,Java类属于src/main/java目录,而属性、配置和JKS文件通常属于src/main/resources目录。根据您确切的 Maven 设置,将 JKS 文件放在 java 目录中可能会导致它从实际的可运行类路径中丢弃。所以你也应该检查一下。