【问题标题】:FileNotFoundException in spring boot jar but the file is presentSpring Boot jar 中的 FileNotFoundException 但文件存在
【发布时间】:2019-08-12 18:17:52
【问题描述】:

当文件明显存在于 jar 中时,我收到 FileNotFoundException。为什么会这样?

java.io.FileNotFoundException: file:/Users/serviceuser/project/coolApp/target/coolApp-1.0-SNAPSHOT.jar!/BOOT-INF/classes!/ssl_certs/mysslstore.jks (No such file or directory)
    at java.base/java.io.FileInputStream.open0(Native Method) ~[na:na]
    at java.base/java.io.FileInputStream.open(FileInputStream.java:219) ~[na:na]
    at java.base/java.io.FileInputStream.<init>(FileInputStream.java:157) ~[na:na]
    at java.base/java.io.FileInputStream.<init>(FileInputStream.java:112) ~[na:na]

但是,我看到文件打包在 jar 中。

jar -tf coolApp-1.0-SNAPSHOT.jar | grep ssl

编辑 我按以下方式加载文件

new FileInputStream(CoolApp.class.getClassLoader().getResource("ssl_certs/mysslstore.jks").getFile())

【问题讨论】:

  • jar 内的文件不是传统文件路径目录结构的一部分。您需要以流的形式获取资源。
  • @Compass 我如上加载了文件
  • 我认为这是认证问题。
  • @LovaChittumuri 这不是认证问题。它是 FileNotFoundException
  • 好的.. 感谢您的确认。

标签: java maven spring-boot


【解决方案1】:

这里:

new FileInputStream(CoolApp.class.getClassLoader().getResource("ssl_certs/mysslstore.jks").getFile());

getFile() 在 jar 中包含的 URL 上调用。
因此,它提供了一个特定的 File 对象,因为它不是文件系统中可直接访问的 File

URL javadoc 确认(重点是我的):

类 URL 代表一个统一资源定位器,一个指向 万维网上的“资源”。 资源可以是 像文件或目录一样简单,也可以是对更多内容的引用 复杂的对象,例如对数据库或搜索的查询 引擎

所以FileInputStream(File) 构造函数不一定能够打开那个“特殊”文件:

FileInputStream 从文件系统中的文件获取输入字节。 可用的文件取决于主机环境。

您可以将您尝试做的事情与以下内容进行比较:

new FileInputStream("/Users/serviceuser/project/coolApp/target/coolApp-1.0-SNAPSHOT.jar!/BOOT-INF/classes!/ssl_certs/mysslstore.jks")

正如您所猜测的,包含在 jar(mysslstore.jks) 中的文件无法被操作系统文件系统解析。

使用返回输入流的getResourceAsStream() 代替。该输入流是指资源所代表的字节序列。这样,客户端代码不再依赖于资源的存储方式。

InputStream is = CoolApp.class.getClassLoader().getResourceAsStream("ssl_certs/mysslstore.jks"));

【讨论】:

  • 有道理。接受了答案,但尚未对其进行测试。
  • getResourceAsStream() 是关键,人们已经忘记了很多次。
  • 没有接受 InputStream 的 new FileInputStream() 的构造函数。无需使用 FileInputStream 包装 .getResourceAsStream。只需CoolApp.class.getClassLoader().getResourceAsStream("ssl_certs/mysslstore.jks") 就足够了
  • @brainstorm 实际上这根本没有意义 :) 谢谢我修正了最后一行。
  • 在这种情况下,CoolApp 将是 Spring 项目的主类的名称......对吗?
【解决方案2】:
I was facing the same issue in spring boot and I have tried many things like bellow but nun of them is working. thease all are working locally but  It is giving FileNotFoundException in dev environmnet because when we build a JAR, the resources get placed into the root directory of the packaged artifacts and our downloaded files I placed inside resource folder. 

Method 1: Working solution for jars
InputStream stram=getClass().getClassLoader().getResourceAsStream(File.separator+"database.properties");
URL url = getClass().getClassLoader().getResource(File.separator+"database.properties");

Only thing which worked is ResourceLoader. Need to Autowire it:
    @Autowired
    ResourceLoader resourceLoader;

        Resource resource = resourceLoader.getResource("classpath:" + File.separatorChar + NPIConstants.VAR_FOLDER
                + File.separatorChar + NPIConstants.TPSPIDsBUCKET_FILENAME);
        InputStreamResource isResource = new InputStreamResource(resource.getInputStream());

Method 1: Not Working solution for jars
ClassLoader loader = Thread.currentThread().getContextClassLoader();
InputStream is = loader.getResourceAsStream("database.properties");
System.out.println(is.available());

Method 2:  Not Working solution for jars
Resource resource = new ClassPathResource("database.properties");
InputStream input = resource.getInputStream();

Method 3: Not Working solution for jars
File file = new File("resources/database.properties");
String absolutePath = file.getAbsolutePath();

Method 4: Not Working solution for jars
File file = new File(getClass().getClassLoader().getResource("database.properties").getFile());

Method 5: Not Working solution for jars
ClassLoader classLoader = getClass().getClassLoader();
classLoader.getResource("database.properties");
String path  = classLoader.getResource("database.properties").getPath();

【讨论】:

  • 不,资源加载器也不适用于 jar。如果可能,请修复格式。
【解决方案3】:

这样的文件需要在资源目录中。

【讨论】:

  • 在源代码中,它在资源中。我上面显示的是 jar 内容。
猜你喜欢
  • 2015-02-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-18
相关资源
最近更新 更多