跳到主要内容Spring Boot 读取 Resource 目录文件的五种常见方式 | 极客日志Javajava
Spring Boot 读取 Resource 目录文件的五种常见方式
Spring Boot 开发中常需读取 src/main/resources 下资源。文章详解 ClassPathResource、ResourceLoader、@Value 注解、ResourceUtils 及 getResourceAsStream 五种读取方式,涵盖 Properties 文件处理。提供 CSV 文件解析实战案例,并解决路径错误、打包后读取失败、中文乱码等常见问题。根据场景选择合适方法可提升配置与静态资源处理效率。
1. 前言
在 Spring Boot 开发中,我们经常需要读取 src/main/resources 目录下的文件。src/main/resources 目录下通常存放配置文件、模板、静态资源、SQL 脚本等,如何在运行时读取这些资源,是每个 Java 开发者必须掌握的技能。
比如下面的 Spring Boot 项目中,资源文件的存储位置:
src/
└── main/
└── resources/
├── static/ # 静态资源
├── templates/ # 模板文件
├── config/ # 配置文件
└── data/ # 数据文件
本文将详细介绍在 Spring Boot 中读取类路径(classpath)下资源的方法,并给出完整的代码示例。
2. 读取 Resource 文件的五种常见方式
2.1 使用 ClassPathResource(推荐)
Spring 提供了 ClassPathResource,可直接从类路径获取资源。
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.FileCopyUtils;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
public class ResourceReader {
public String readWithClassPathResource(String filePath) throws Exception {
ClassPathResource resource = new ClassPathResource(filePath);
try (InputStreamReader reader = new InputStreamReader(
resource.getInputStream(), StandardCharsets.UTF_8)) {
return FileCopyUtils.copyToString(reader);
}
}
}
String content = readWithClassPathResource("data/sample.txt");
System.out.println(content);
2.2 使用 ResourceLoader
ResourceLoader 是 Spring 上下文提供的通用资源加载接口,支持多种前缀(classpath:、file:、http: 等)。
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
@Component
public class ResourceService {
private final ResourceLoader resourceLoader;
public ResourceService(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
}
public String readWithResourceLoader(String location) throws Exception {
Resource resource = resourceLoader.getResource(location);
try (InputStream in = resource.getInputStream()) {
byte[] bytes = in.readAllBytes();
return new String(bytes, StandardCharsets.UTF_8);
}
}
}
String text = resourceLoaderService.readWithResourceLoader("classpath:data/sample.txt");
2.3 使用 @Value 注解
如果只是读取小片段文本或 URL,可直接在字段或方法参数上使用 @Value。
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
@Component
public class ValueResourceReader {
@Value("classpath:data/sample.txt")
private Resource configFile;
public String readConfig() throws IOException {
return new String(configFile.getInputStream().readAllBytes(), StandardCharsets.UTF_8);
}
}
2.4 使用 ResourceUtils
ResourceUtils 是 Spring 内置的一个工具类,可以将类路径资源转换为 File 或 URL,适用于需要 java.io.File 操作的场景。
import org.springframework.stereotype.Service;
import org.springframework.util.ResourceUtils;
import java.io.File;
import java.nio.file.Files;
import java.nio.charset.StandardCharsets;
@Service
public class ResourceUtilsService {
public String readWithResourceUtils(String location) throws Exception {
File file = ResourceUtils.getFile(location);
byte[] bytes = Files.readAllBytes(file.toPath());
return new String(bytes, StandardCharsets.UTF_8);
}
}
2.5 通过 getResourceAsStream
最原生的方式:通过 Class 或 ClassLoader 的 getResourceAsStream。
import org.springframework.stereotype.Service;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.stream.Collectors;
@Service
public class NativeStreamService {
public String readWithGetResourceAsStream(String path) {
try (InputStream in = this.getClass().getClassLoader().getResourceAsStream(path);
BufferedReader reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8))) {
return reader.lines().collect(Collectors.joining(System.lineSeparator()));
} catch (Exception e) {
throw new RuntimeException("读取资源失败", e);
}
}
}
补充:读取 Properties 文件
如果读取的配置文件是 Properties 文件,依然可以使用 ClassPathResource 读取。
import org.springframework.core.io.ClassPathResource;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class PropertiesReader {
public Properties readProperties(String filePath) throws IOException {
ClassPathResource resource = new ClassPathResource(filePath);
try (InputStream input = resource.getInputStream()) {
Properties properties = new Properties();
properties.load(input);
return properties;
}
}
}
3. 完整实战案例:读取 CSV 文件并处理
3.1 创建测试文件
在 src/main/resources/data/ 下创建 users.csv:
id,name,email
1,张三,zhangsan@example.com
2,李四,lisi@example.com
3.2 创建 CSV 处理器
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
@Service
public class CsvService {
public List<User> parseCsv(String filePath) throws Exception {
ClassPathResource resource = new ClassPathResource(filePath);
List<User> users = new ArrayList<>();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(resource.getInputStream()))) {
String line = reader.readLine();
while ((line = reader.readLine()) != null) {
String[] parts = line.split(",");
if (parts.length == 3) {
users.add(new User(Integer.parseInt(parts[0]), parts[1], parts[2]));
}
}
}
return users;
}
public static class User {
private int id;
private String name;
private String email;
}
}
3.3 创建 Controller 测试
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class CsvController {
private final CsvService csvService;
public CsvController(CsvService csvService) {
this.csvService = csvService;
}
@GetMapping("/users")
public List<CsvService.User> getUsers() throws Exception {
return csvService.parseCsv("data/users.csv");
}
}
4. 常见问题解决方案
问题 1:文件路径错误
错误信息: java.io.FileNotFoundException: class path resource [xxx] cannot be opened because it does not exist
- 检查文件是否在 src/main/resources 目录下
- 使用正确路径(区分大小写)
- 文件路径前不要加
/(正确:data/file.txt,错误:/data/file.txt)
问题 2:打包后文件读取失败
错误信息: FileNotFoundException when reading from JAR
- 使用 ClassPathResource 而不是 File
- 避免使用
new File("classpath:...") 语法
- 使用
getResourceAsStream() 方法
问题 3:读取 Resource 目录文件中文乱码
new InputStreamReader(resource.getInputStream(), StandardCharsets.UTF_8);
5. 总结
Spring Boot 提供了多种灵活的方式来读取 resource 目录下的文件。根据不同场景选用最合适的方式:
- 如果需要 Spring 统一管理,推荐
ResourceLoader;
- 若只是简单注入小文件,可选
@Value;
- 如果需要操作 File,可用
ResourceUtils。
掌握这些方法,能让开发者在处理配置、模板、静态资源等场景时更得心应手。
相关免费在线工具
- Keycode 信息
查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
- Escape 与 Native 编解码
JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
- JavaScript / HTML 格式化
使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
- JavaScript 压缩与混淆
Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
- Base64 字符串编码/解码
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
- Base64 文件转换器
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online