Spring应用打包为Jar后静态资源路径异常问题排查
问题原因与解决方案
路径中"!"的含义
这个"!"是Java用来标识Jar包内部资源的分隔符,完整路径jar:file:/xxx.jar!/BOOT-INF/classes!/static/logo_joyjob.png表示:logo_joyjob.png是在joyjobcore-0.0.1-SNAPSHOT.jar压缩包内部的BOOT-INF/classes/static目录下,它不是文件系统中独立存在的真实文件,而是Jar包内的一个压缩条目。
为什么IntelliJ运行正常,Jar包运行报错?
IntelliJ启动应用时,直接从本地磁盘的build/classes目录加载资源——这些是真实存在的文件,所以ResourceUtils.getFile()能正常找到对应路径。但打包成Jar后,资源被压缩到Jar包内部,无法通过File对象访问,此时用ResourceUtils.getFile()就会抛出文件找不到的异常。
解决方法
修改CardUploader类中读取静态资源的代码,放弃ResourceUtils.getFile(),改用Spring的资源加载方式读取资源流:
方案1:注入ResourceLoader
import org.springframework.core.io.ResourceLoader; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import java.io.InputStream; import java.io.IOException; @Component public class CardUploader { private final ResourceLoader resourceLoader; public CardUploader(ResourceLoader resourceLoader) { this.resourceLoader = resourceLoader; } @PostConstruct public void onInit() { try (InputStream inputStream = resourceLoader.getResource("classpath:static/logo_joyjob.png").getInputStream()) { // 在这里处理图片资源流,比如读取内容、转换为字节数组等 } catch (IOException e) { // 处理资源加载异常 e.printStackTrace(); } } }
方案2:用@Value直接注入Resource
import org.springframework.core.io.Resource; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import java.io.InputStream; import java.io.IOException; @Component public class CardUploader { @Value("classpath:static/logo_joyjob.png") private Resource logoResource; @PostConstruct public void onInit() { try (InputStream inputStream = logoResource.getInputStream()) { // 处理图片资源流 } catch (IOException e) { // 处理异常 e.printStackTrace(); } } }
关于build.gradle的配置
你的build.gradle配置没有问题,Spring Boot默认会把src/main/resources下的静态资源打包到Jar包的BOOT-INF/classes目录中,资源本身是存在的,问题完全出在代码读取资源的方式上。
内容的提问来源于stack exchange,提问作者Bogdan Lashkov
相关产品推荐
相关产品推荐

