SpringBoot jar包resource文件内容读取

本文介绍了一种解决SpringBoot项目中无法直接读取jar包内部资源文件的问题的方法。通过自定义ResourceReader类,实现了从classpath中加载资源,并将其临时复制到文件系统,以便能够按需读取内容。

文章目录

读取springboot jar包文件会出现如下异常

class path resource [mock/listResumeJobVideoCard.json] cannot be resolved to absolute file path because it does not reside in the file system: jar:file:/data/java-camx-live-c/lib/c-1.10.0.RELEASE.jar!/BOOT-INF/classes!/mock/listResumeJobVideoCard.json

java.io.FileNotFoundException: class path resource [mock/listResumeJobVideoCard.json] cannot be resolved to absolute file path because it does not reside in the file system: jar:file:/data/java-camx-live-c/lib/c-1.10.0.RELEASE.jar!/BOOT-INF/classes!/mock/listResumeJobVideoCard.json
	at org.springframework.util.ResourceUtils.getFile(ResourceUtils.java:217)
	at org.springframework.core.io.AbstractFileResolvingResource.getFile(AbstractFileResolvingResource.java:154)
	at com.zhaopin.live.service.JobVideoCardServiceImpl$FileReader.load(JobVideoCardServiceImpl.java:72)
	at com.zhaopin.live.service.JobVideoCardServiceImpl.listResumeJobVideoCard(JobVideoCardServiceImpl.java:56)
	at com.zhaopin.live.service.JobVideoCardServiceImpl$$FastClassBySpringCGLIB$$6c95e52e.invoke(<generated>)
	at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:752)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
	at org.springframework.validation.beanvalidation.MethodValidationInterceptor.invoke(MethodValidationInterceptor.java:119)
	at com.zhaopin.boot.autoconfigure.thrift.validation.ZhaopinMethodValidationInterceptor.invoke(ZhaopinMethodValidationInterceptor.java:37)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691)
	at com.zhaopin.live.service.JobVideoCardServiceImpl$$EnhancerBySpringCGLIB$$872fbc57.listResumeJobVideoCard(<generated>)

经过踩坑最终结局问题。

ResourceReader

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.springframework.util.ResourceUtils;

import java.io.File;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;

/**
 * Resource 文件内容读取器
 * @author 石冬冬(Chris Suk)
 * @since 2022/10/12 9:57 AM
 */
@Slf4j
public class ResourceReader {
    /**
     * 读取 resources 下文件内容
     * @param resourcePath
     * @return
     */
    public static String read(String resourcePath){
        String data = "";
        try {
            InputStream inputStream = ResourceReader.class.getClassLoader().getResourceAsStream(resourcePath);
            File tmpFile = new File("/tmp/" + resourcePath);
            if (!tmpFile.exists()) {
                FileUtils.copyToFile(inputStream, tmpFile);
            }
            File file = ResourceUtils.getFile(tmpFile.getPath());
            data = FileUtils.readFileToString(file, StandardCharsets.UTF_8);
        } catch (Exception e) {
            log.error("读取文件内容异常", e);
        }
        return data;
    }
}

应用

 public ListResumeVideoCardDTO listResumeJobVideoCard() {
     String data = ResourceReader.read("mock/listResumeJobVideoCard.json");
     return JSON.parseObject(data, ListResumeVideoCardDTO.class);
 }
<think>根据用户问题,需要解决在Spring Boot应用中从JAR读取JSON文件的问题。结合引用内容,以下为可靠方法: ### 方法一:使用SpringResourceUtils(仅适用于开发环境) 在开发阶段(IDE中)可用,但**打JAR后失效**(引用1、2、3均指出此问题): ```java File jsonFile = ResourceUtils.getFile("classpath:json/file.json"); ``` **不推荐**,因为JAR文件不是独立文件而是资源流。 ### 方法二:使用ClassPathResource(推荐) 通过`ClassPathResource`获取资源流,兼容JAR环境: ```java import org.springframework.core.io.ClassPathResource; import org.apache.commons.io.IOUtils; // 读取JSON文件为字符串 ClassPathResource resource = new ClassPathResource("json/file.json"); InputStream inputStream = resource.getInputStream(); String json = IOUtils.toString(inputStream, StandardCharsets.UTF_8); ``` ### 方法三:使用ClassLoader(底层方案) 直接通过类加载器获取资源流: ```java InputStream inputStream = getClass().getClassLoader().getResourceAsStream("json/file.json"); String json = new String(inputStream.readAllBytes(), StandardCharsets.UTF_8); ``` ### 注意事项 1. **文件路径**:路径不以`/`开头,例如`json/file.json`表示从classpath的`json`目录下读取。 2. **依赖**:若使用`IOUtils`,需添加commons-io依赖(引用2): ```xml <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.11.0</version> </dependency> ``` 3. **资源位置**:JSON文件需放在`src/main/resources/json/`目录下。 ### 完整示例 ```java import org.springframework.core.io.ClassPathResource; import org.apache.commons.io.IOUtils; import java.nio.charset.StandardCharsets; public String readJsonFromClasspath() throws IOException { ClassPathResource resource = new ClassPathResource("json/file.json"); try (InputStream inputStream = resource.getInputStream()) { return IOUtils.toString(inputStream, StandardCharsets.UTF_8); } } ``` ### 引用说明 - 引用[2]和[3]验证了`ResourceUtils.getFile`在JAR中失效,推荐使用流式读取。 - 引用[4]提到从JAR所在目录读取外部文件(非JAR内),与本需求不同。 §§相关问题§§ 1. 如何在Spring Boot读取JAR外的配置文件? 2. Spring Boot资源加载机制是怎样的? 3. 如何解决JAR中资源文件访问的性能问题?</think>### Spring Boot 读取 JAR 内 JSON 文件的方法 在 Spring Boot 应用中读取 JAR 内的 JSON 文件,**必须使用资源流方式**而非文件路径方式,因为 JAR 中的文件不是独立文件系统对象。以下是可靠解决方案: #### ✅ 推荐方法:使用 `ClassPathResource` + 流读取 ```java import org.springframework.core.io.ClassPathResource; import org.apache.commons.io.IOUtils; // 读取 classpath:json/data.json 文件 ClassPathResource resource = new ClassPathResource("json/data.json"); try (InputStream inputStream = resource.getInputStream()) { String jsonContent = IOUtils.toString(inputStream, "UTF-8"); // 使用 fastjson 解析 JSONObject jsonObject = JSON.parseObject(jsonContent); System.out.println(jsonObject); } ``` #### ✅ 备选方法:使用 `ClassLoader` ```java InputStream inputStream = getClass().getClassLoader() .getResourceAsStream("json/data.json"); String jsonContent = new String(inputStream.readAllBytes(), StandardCharsets.UTF_8); ``` --- ### 📌 关键注意事项 1. **文件位置** JSON 文件需放在 `src/main/resources/json/` 目录下,打后位于 JAR 的 `BOOT-INF/classes/json/` 中 2. **必需依赖** 在 `pom.xml` 中添加: ```xml <!-- Apache Commons IO --> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.11.0</version> </dependency> <!-- FastJSON --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.83</version> </dependency> ``` 3. **错误做法** ❌ 避免使用 `ResourceUtils.getFile()`(引用1,2,3 已证明在 JAR 中失效): ```java // 打JAR后无法运行! File file = ResourceUtils.getFile("classpath:json/data.json"); ``` --- ### 💡 原理解析 当 Spring Boot 应用打JAR 后,所有资源文件被压缩到存档中。`ClassPathResource` 通过类加载器访问 JAR 内部资源流,而传统 `File` API 只能访问文件系统实体(引用2,3)。此方法符合 Java 资源加载规范,确保开发环境和生产环境行为一致[^1][^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值