环境:Ubuntu 18 + Spring boot 2.0 + JDK 11
当应用程序在IntelliJ中运行时,它可以正常运行,但是在Spring boot maven插件打包文件之后读取文件时,它不能运行。
PS:确实可以在打包的jar文件中找到该文件!
npx tsc
答案 0 :(得分:0)
您很可能试图使用java.io
类来加载类路径资源。这将行不通,java.io
类仅用于文件系统操作。
在JAR外部提取jmxremote.password
或使用常规InputStream
作为类路径资源对其进行访问,例如通过使用Class.getResourceAsStream()
:
try (InputStream in : getClass().getResourceAsStream("/jmxremote.password")) {
// read input
}
答案 1 :(得分:0)
TL; DR
在Spring框架环境中,重点是使用Spring实用工具来处理资源(如ResourceUtils
class),这些资源很好地封装了底层的,依赖于操作系统的IO操作。 ResourceUtils
已经包含多个陷阱,以确定正在运行的项目是爆炸(在IDE中运行)还是打包的(在JAR文件中)。
Karol提供的答案似乎最简单并且相对防弹,直到您需要某种程度的灵活性来指定文件位置(在jar文件中,但可以在外部定义它并在文件系统中的某个位置提供该可能性) )。那么使用getResourceAsStream()
方法的方法将不起作用。
标准Java IO(java.nio
)使用FileSystemProvider
类委派IO操作(如创建,读取和删除文件)。
提供商通过URI 方案进行标识。默认提供程序由URI方案“文件”标识。它创建FileSystem,该文件系统提供对Java虚拟机可访问的文件系统的访问。 FileSystems类定义如何定位和加载文件系统提供程序。
因此,如果您的文件位于文件系统上的某个位置,则没有问题,并且一切正常。从技术上讲,Application.class.getResource("").toURI()
返回的URL以 file:// 开头,并包含有效的文件系统路径。
话虽如此,当您的文件“降落”在jar文件中时,Application.class.getResource("").toURI()
返回的内容类似于 file:// {jar-location}!/ (请注意惊叹号)。标记),这不是有效的文件架构路径,Java不知道如何处理。其他文件系统提供者需要注册。
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);
新文件系统提供程序的安装是全局的,应该只安装一次。