Spring中getResource()获取资源路径:Jar包运行时getFile()抛异常
解决Jar包中Resource.getFile()抛出FileNotFoundException的问题
嘿,这个坑我太熟了!你碰到的问题核心原因很明确:Jar包内的资源并不是文件系统中的真实物理文件,而是Jar归档文件里的一个条目。resource.getFile()方法只能处理文件系统中存在的资源(比如你在IntelliJ里运行时,资源是放在项目编译后的classes目录下的真实文件),但打包成Jar后,这个方法就彻底失效了——因为根本不存在对应的绝对文件路径。
下面给你几种不同场景下的正确处理方式:
场景1:只是需要读取资源内容(最常见)
如果你的目的是读取.properties文件的内容,完全不需要获取什么路径,直接用getResourceAsStream()读取输入流即可,这是跨环境(IDE/Jar)通用的方式:
Resource[] resources = context.getResources("classpath*:**/i18n/**/*.properties"); for (Resource resource : resources) { try (InputStream inputStream = resource.getInputStream()) { Properties props = new Properties(); props.load(inputStream); // 这里就可以操作props里的配置了 } catch (IOException e) { // 处理异常 } }
场景2:需要获取资源的标识字符串(不是真实文件路径)
如果只是需要一个能标识这个资源的字符串(比如日志输出、资源定位),可以用getURI()或者getURL()来获取资源的URI/URL字符串,这个在Jar环境下是有效的:
String resourceUri = resources[i].getURI().toString(); // 得到类似 jar:file:/home/mariusz/.../app-3.0.0-SNAPSHOT-all.jar!/i18n/test.properties 的字符串 // 或者用URL String resourceUrl = resources[i].getURL().toString();
场景3:必须拿到真实文件系统路径(极少数情况)
如果你的业务逻辑真的依赖真实文件路径(比如某些第三方库只接受File对象),那只能把Jar里的资源提取到临时文件中,用完再清理:
Resource resource = resources[i]; File tempFile = File.createTempFile("i18n-temp-", ".properties"); // 设置JVM退出时自动删除临时文件 tempFile.deleteOnExit(); // 将资源内容复制到临时文件 try (InputStream is = resource.getInputStream(); OutputStream os = new FileOutputStream(tempFile)) { // 手动实现字节流复制,也可以用Apache Commons IO的IOUtils.copy简化代码 byte[] buffer = new byte[1024]; int bytesRead; while ((bytesRead = is.read(buffer)) != -1) { os.write(buffer, 0, bytesRead); } } catch (IOException e) { // 处理异常 } // 现在就能拿到真实文件路径了 String realFilePath = tempFile.getAbsolutePath();
总结一下:尽量避免依赖getResource().getFile(),优先使用输入流操作资源,这是最稳妥的跨环境方案。
内容的提问来源于stack exchange,提问作者Mariusz.v7
相关产品推荐
相关产品推荐

