首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >无法读取spring boot打包jar文件

无法读取spring boot打包jar文件
EN

Stack Overflow用户
提问于 2019-01-06 00:17:13
回答 2查看 1.7K关注 0票数 3

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

当应用程序在IntelliJ中运行时,它会正确执行,但在Spring boot maven插件打包文件之后读取文件时,它就不会正确执行。

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

代码语言:javascript
运行
复制
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
EN

回答 2

Stack Overflow用户

发布于 2019-01-06 00:39:52

您很可能正在尝试使用java.io类加载类路径资源。这是行不通的,java.io类只为文件系统操作而设计。

从JAR外部提取jmxremote.password,或者使用常规InputStream将其作为类路径资源进行访问,例如使用Class.getResourceAsStream()

代码语言:javascript
运行
复制
try (InputStream in : getClass().getResourceAsStream("/jmxremote.password")) {
  // read input
}
票数 0
EN

Stack Overflow用户

发布于 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()不知道如何处理它。另一个文件系统提供程序需要注册。

代码语言:javascript
运行
复制
FileSystems.newFileSystem(uri, emptyMap());

Java计算出(基于URI)方案并注册一个新的文件系统。从现在开始,可以使用标准的java.nio文件操作。

例如,如果您在/webapp文件夹中有一些文件,这些文件可以(但不需要)在jar文件中,并且您想要列出它们。

代码语言:javascript
运行
复制
// 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);

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54053817

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档