专业的JAVA编程教程与资源

网站首页 > java教程 正文

Spring Boot JAR 包资源访问踩坑:cannot be resolved to absolute file

temp10 2025-09-13 09:06:26 java教程 3 ℃ 0 评论

在 IDE 中运行 Spring Boot 项目,读取 classpath 下的脚本或配置文件,代码运行得顺畅无比。如下:

String content = FileUtils.readFileToString(
  						new ClassPathResource("config/app-config.yml").getFile(),"utf-8");

但打包成 JAR 部署到服务器后,却抛出这个错误:

Spring Boot JAR 包资源访问踩坑:cannot be resolved to absolute file

class path resource [config/app-config.yml] cannot be resolved to absolute file path 
because it does not reside in the file system

看着这行报错,一脸懵:为什么 IDE 正常,JAR 包就不行?

原因分析

在开发环境中(比如 IntelliJ IDEA):资源文件(如
src/main/resources/config/app-config.yml)存储在target/classes 目录下;但项目打包成 Spring Boot 的
Fat JAR 后,资源被压缩到 JAR 包的 BOOT-INF/classes/ 目录,路径变成: jar:file:/app.jar!/BOOT-INF/classes!/config/app-config.yml。

接下来,我们继续分析ClassPathResource.getFile()的源码,如下:

// org.springframework.core.io.AbstractFileResolvingResource#getFile()
public File getFile() throws IOException {  
    URL url = getURL();  
    // ResourceUtils.URL_PROTOCOL_VFS = "vfs"
    if (url.getProtocol().startsWith(ResourceUtils.URL_PROTOCOL_VFS)) {  
       return VfsResourceDelegate.getResource(url).getFile();  
    }  
    return ResourceUtils.getFile(url, getDescription());  
}

// org.springframework.util.ResourceUtils#getFile(java.net.URL, java.lang.String)
public static File getFile(URL resourceUrl, String description) throws FileNotFoundException {  
    // URL_PROTOCOL_FILE = "file" 
    if (!URL_PROTOCOL_FILE.equals(resourceUrl.getProtocol())) {  
       throw new FileNotFoundException(  
             description + " cannot be resolved to absolute file path " +  
             "because it does not reside in the file system: " + resourceUrl);  
    }  
    try {  
       return new File(toURI(resourceUrl).getSchemeSpecificPart());  
    }  
    catch (URISyntaxException ex) {  
       // Fallback for URLs that are not valid URIs (should hardly ever happen).  
       return new File(resourceUrl.getFile());  
    }  
}

通过源码可知 ClassPathResource.getFile()报错的原因:资源不是 file:// 协议,直接抛异常

如何解决

1.使用InputStream读取

import org.springframework.core.io.ClassPathResource;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

public class ResourceReader {
    public String readScript() throws IOException {
        ClassPathResource resource = new ClassPathResource("config/app-config.yml");
        try (var inputStream = resource.getInputStream()) {
            return new String(inputStream.readAllBytes(), StandardCharsets.UTF_8);
        }
    }
}

2.转换为临时文件

public class ResourceToFile {
    public File convertToFile() throws IOException {
        ClassPathResource resource = new ClassPathResource("config/app-config.yml");
        Path tempFile = Files.createTempFile("cust-fund-script", ".tmp");
        try (var inputStream = resource.getInputStream()) {
            Files.copy(inputStream, tempFile, StandardCopyOption.REPLACE_EXISTING);
        }
        File file = tempFile.toFile();
        file.deleteOnExit(); // 自动清理
        return file;
    }
}

感谢您的阅读!希望这部分内容对您有所启发。如果您觉得有价值,请不吝点赞支持,并在评论区留下您的想法,一起交流学习!别忘了关注我哦!

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表