密钥库没有从jar中加载JKS文件

时间:2014-08-19 23:03:10

标签: java classloader loading

经过几个小时的斗争,我开始变得非常沮丧。

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

这是项目的分发方式

ProjectFolder
-src
--package.name
---JKS File
---Class calling the resource retrieval and loading into the keystore

我想我几乎尝试过this.getClass()。getClassLoader()。getResourceAsStream(“jksFile.jks”)的每一个组合我都能想到。

我提前道歉,因为没有更具体的代码,但我完全忘记了我尝试过的东西和我没有的东西。

HELP!

提前致谢

3 个答案:

答案 0 :(得分:2)

如果是战争文件:

在构建和运行项目时,.class将不再位于此位置(/ src),它将转到WEB-INF / classes / ...,所以,也许你可以试着把你的JKS文件在那里,或者在getResourceAsStream()中从类到src的引用。

war文件夹的文件夹层次结构的有用链接:http://www.yolinux.com/TUTORIALS/Java-WAR-files.html

答案 1 :(得分:1)

通过获取Class,有两种主要方式可以通过Classloader对象和getResourceAsStream访问类路径中的资源。

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

  

资源的名称是'/' - 标识资源的分隔路径名。

而且,在探索类路径时,搜索顺序也很清晰

  

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

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

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

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

所以......考虑到以下项目结构:

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目录中可能会导致它从实际的可运行类路径中被丢弃。所以你也应该检查一下。

答案 2 :(得分:0)

假设jar包含 src下的文件夹结构,它包含已编译的.class文件以及甚至包含源.java的文件。 file(s)(使目录名src误导):

  • this.getClass().getResourceAsStream(String) 或其他方式获取类MyClass.class然后.getResourceAsStream(String) 将resource-name视为相对于包含类

  • 的package =目录
  • this.getClass().getClassLoader().getResourceAsStream(String) 或其他方式查找类似athread.getContextClassLoader()然后.getResourceAsStream(String)的类加载器 将资源名称视为相对于jar文件的根目录,因此您需要"package/names/jksfile.jks"。 请记住jar 中的包路径使用斜杠,而在Java源代码中,它们使用点。

(将源文件放在src/package/names/MyClass.java和编译文件下时,目录'src'和'bin'通常使用且有用 在镜像层次结构bin/package/names/MyClass.class中。)