Heroku部署Spring Boot应用:运行时无法加载Classpath资源
解决Spring Boot部署Heroku后无法访问resources资源文件的问题
这个问题我太熟了!当你把Spring Boot项目打包成Jar部署到Heroku后,原来用File或者Paths直接访问src/main/resources下文件的方式就彻底失效了——原因很简单:此时你的资源文件是嵌入在Jar包内部的条目,不是服务器文件系统上的独立文件,用文件系统路径去自然找不到,所以才会抛出NoSuchFileException。
下面给你几个可靠的解决方案,都是Spring生态里标准的资源访问方式:
方案1:用ClassPathResource直接读取资源
这是最直接的方式,适合在任意Spring管理的Bean或者普通类中使用:
import org.springframework.core.io.ClassPathResource; import java.io.InputStream; import java.nio.charset.StandardCharsets; public void loadResourceFile() { // 注意路径:直接写resources下的相对路径,比如这里的setup_data/app_xxx.json ClassPathResource resource = new ClassPathResource("setup_data/app_xxx.json"); try (InputStream inputStream = resource.getInputStream()) { // 将输入流转成字符串,后续可以解析JSON或者做其他处理 String fileContent = new String(inputStream.readAllBytes(), StandardCharsets.UTF_8); // 你的业务逻辑写在这里... } catch (Exception e) { // 异常处理,比如打印日志或者抛出业务异常 e.printStackTrace(); } }
方案2:通过ResourceLoader注入加载资源
如果你的类是Spring管理的Bean,推荐用这种依赖注入的方式,更符合Spring的设计理念:
import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; import org.springframework.stereotype.Component; import java.io.InputStream; import java.nio.charset.StandardCharsets; @Component public class ResourceService { private final ResourceLoader resourceLoader; // 通过构造器注入ResourceLoader(Spring会自动提供实例) public ResourceService(ResourceLoader resourceLoader) { this.resourceLoader = resourceLoader; } public String loadDdlScript() throws Exception { // 用classpath:前缀指定类路径下的资源,这里示例加载ddl目录下的SQL脚本 Resource ddlResource = resourceLoader.getResource("classpath:ddl/init_script.sql"); try (InputStream inputStream = ddlResource.getInputStream()) { return new String(inputStream.readAllBytes(), StandardCharsets.UTF_8); } } }
关键注意事项
- 绝对不要用
resource.getFile()!这个方法只有当资源存在于本地文件系统(比如IDE开发模式)时才有效,Jar包内的资源调用这个方法一定会抛出异常,必须用getInputStream()来读取内容。 - 资源路径要写对:
src/main/resources是类路径的根目录,所以直接写目录+文件名即可,比如setup_data/app.json,或者加上classpath:前缀(两种写法都可以)。 - 本地测试尽量模拟Jar环境:本地开发时IDE是直接解压资源到文件系统的,所以用
File可能也能跑通,但部署到Heroku就会挂。建议本地用mvn spring-boot:run或者打包成Jar后运行测试,提前发现问题。
内容的提问来源于stack exchange,提问作者edoDev
相关产品推荐
相关产品推荐

