繁体   English   中英

Spring Boot jar 中的 FileNotFoundException 但文件存在

[英]FileNotFoundException in spring boot jar but the file is present

当文件明显存在于 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())

这里 :

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

getFile()在 jar 中包含的URL上调用。
因此,它提供了一个特定的File对象,因为它不是在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"));

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

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();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM