无法读取spring boot包装jar文件

时间:2019-01-05 16:17:13

标签: java spring-boot ubuntu

环境:Ubuntu 18 + Spring boot 2.0 + JDK 11

当应用程序在IntelliJ中运行时,它可以正常运行,但是在Spring boot maven插件打包文件之后读取文件时,它不能运行。

PS:确实可以在打包的jar文件中找到该文件!

npx tsc

2 个答案:

答案 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);

新文件系统提供程序的安装是全局的,应该只安装一次。