环境: Ubuntu 18 + Spring boot 2.0 + JDK 11
当应用程序在IntelliJ中运行时,它会正确执行,但在Spring boot maven插件打包文件之后读取文件时,它就不会正确执行。
PS:这个文件确实可以在打包的jar文件中找到!
java.io.FileNotFoundException: class path resource [jmxremote.password]
cannot be resolved to absolute file path because it does not reside in the
file system: jar:file:/home/XXX/YYY/target/YYY-1.0-Final.jar!/BOOT-
INF/classes!/jmxremote.password发布于 2019-01-06 00:39:52
您很可能正在尝试使用java.io类加载类路径资源。这是行不通的,java.io类只为文件系统操作而设计。
从JAR外部提取jmxremote.password,或者使用常规InputStream将其作为类路径资源进行访问,例如使用Class.getResourceAsStream()
try (InputStream in : getClass().getResourceAsStream("/jmxremote.password")) {
// read input
}发布于 2019-01-06 03:50:47
TL;DR
在Spring Framework环境中,重点关注使用Spring实用工具来处理资源(比如ResourceUtils class),这些资源很好地封装了底层的、依赖于操作系统的IO操作。ResourceUtils已经包含了多个陷阱,用于判断您正在运行的项目是分解的(在集成开发环境中运行)还是打包的(在JAR文件中)。
Karol提供的答案似乎是最简单的,而且相对来说是防弹的,除非您需要一定程度的灵活性来指定文件位置(在jar文件内,但可以在外部定义它并在文件系统中的某个位置提供)。那么使用getResourceAsStream()方法的方法将不起作用。
标准Java IO (java.nio)使用FileSystemProvider类来委派IO操作(如创建、读取和删除文件)。
提供者由URI方案标识。默认提供者由URI方案“file”标识。它创建FileSystem,提供对Java虚拟机可访问的文件系统的访问。FileSystems类定义如何定位和加载文件系统提供程序。
因此,如果您的文件位于文件系统中的某个位置,则不会出现任何问题,并且一切工作正常。从技术上讲,Application.class.getResource("").toURI()返回的URL以file://开头,并包含有效的文件系统路径。
话虽如此,当您的文件“登陆”到jar文件中时,Java语言返回的内容更像是file://{jar-location}!/ (注意感叹号),它不是有效的文件模式路径,Application.class.getResource("").toURI()不知道如何处理它。另一个文件系统提供程序需要注册。
FileSystems.newFileSystem(uri, emptyMap());Java计算出(基于URI)方案并注册一个新的文件系统。从现在开始,可以使用标准的java.nio文件操作。
例如,如果您在/webapp文件夹中有一些文件,这些文件可以(但不需要)在jar文件中,并且您想要列出它们。
// Load zip specific filesystem provider when run from inside a fat-jar
URI uri = Application.class.getResource("").toURI();
if (uri.toString().contains("!")) {
FileSystems.newFileSystem(uri, emptyMap());
}
URI rootFolder = Application.class.getResource("/webapp").toURI();
List<Path> banners = Files.list(Paths.get(rootFolder))
.collect(Collectors.toList());
Random rand = new Random();
Path path = banners.get(rand.nextInt(banners.size()));
log.info("Random image: {}", path.getFileName());
byte[] bytes = Files.readAllBytes(path);新文件系统提供程序的安装是全局的,应该只安装一次。
https://stackoverflow.com/questions/54053817
复制相似问题