密钥库未从 jar 中加载 JKS 文件

Car*_* B. 5 java loading classloader

经过几个小时的斗争后,我开始感到非常沮丧。

我有一个 JKS 服务器文件,我想从 jar 中加载它。只要文件在 Jar 之外,使用 FileInputStream 就可以了,但是一旦我尝试将其更改为 getResourceAsStream,它就不会接受它,并说(没有这样的文件或目录)。

这就是项目的分发方式

ProjectFolder
-src
--package.name
---JKS File
---Class calling the resource retrieval and loading into the keystore
Run Code Online (Sandbox Code Playgroud)

我想我已经尝试了几乎所有我能想到的 this.getClass().getClassLoader().getResourceAsStream("jksFile.jks") 组合。

我提前为没有更具体地说明代码而道歉,但我实际上已经忘记了我尝试过什么和没有尝试过什么。

帮助!

提前致谢

GPI*_*GPI 1

访问类路径内的资源有两种主要方式:通过Class对象,以及通过Classloader, 通过获取getResourceAsStream

最终,实现资源查找的精确规则取决于类加载器。但大部分都是明确规定的。按名称查找资源。

资源的名称是标识资源的“/”分隔的路径名。

并且,在探索类路径时,搜索顺序也很明确

该方法首先会在父类加载器中搜索资源;如果父级为空,则搜索虚拟机内置的类加载器的路径。如果失败,此方法将调用 {@link #findResource(String)} 来查找资源。

findResource是依赖于实现的部分。然而,大多数 Java 类加载器都是URLClassLoader某种类型的,并且它们的实现知道如何探索类路径条目(在文件系统上或 JAR 文件内,甚至是远程文件),以将名称解析为所述条目内的相对或绝对路径。

因此,简而言之:您可以用来getResourceByName探索类路径,通过类路径中的相对或绝对路径查找文件。

Class#getResourceAsStream和之间的区别ClassLoader#getResourceAsStream在于,Class版本会将相对路径解释为相对于 的Class包,而ClassLoader版本将从类路径的根目录开始。

所以...给出以下项目结构:

src
  name
    gpi
      file.txt
      Test.java  
Run Code Online (Sandbox Code Playgroud)

这个 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));
}
Run Code Online (Sandbox Code Playgroud)

请注意文档思想中的细节,如

// 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");
Run Code Online (Sandbox Code Playgroud)

如果您尝试此处列出的组合有效,但它们实际上不起作用,那么要么您有一个“时髦”的类加载器(这绝对不应该发生在简单的项目上),要么您的编译器/打包器设置(maven 或 eclipse 或其他) )的设置方式是从编译/打包结果 (JAR) 中丢弃 JKS 文件。

一般来说,在maven项目中,Java类属于src/main/java目录,而属性、配置和JKS文件通常属于src/main/resources目录。根据您的具体 Maven 设置,将 JKS 文件放入 java 目录中可能会导致它从实际的可运行类路径中被丢弃。所以你也应该检查一下。