开发必备!Spring Boot 项目中 resources 文件读取的 9 大方案详解

在 Spring Boot 项目中,resources 目录承载着大量的关键资源,如配置文件、模板文件、脚本资源、数据文件等。而如何以合适的方式高效、安全地读取这些资源,往往是开发者绕不过的关键环节。

不同的资源加载方式有不同的适用场景和底层机制,如果使用不当,不仅可能导致资源读取失败,还可能影响程序的可移植性和扩展性。

本文将为你系统性地讲解 Spring Boot 中读取 resources 文件的 9 种主流方式,并在最后附上一套完整的控制器 Demo 示例,集中展示这些方式在实际项目中的统一实现,帮助你在开发中快速定位最适合的资源加载方案。

资源读取的 9 大方式概览

我们先逐一列出每种方式的核心思路与适用场景。

1、ClassLoader.getResourceAsStream() —— 通用类加载器读取方式

说明:以类加载器为起点,查找资源路径。

InputStream inputStream = getClass().getClassLoader().getResourceAsStream("config/sample.txt");
  • 不依赖 Spring,适用于任意 Java 项目;

  • 路径从 classpath 根路径开始,不需要加 /

2、Class.getResourceAsStream() —— 相对于类路径加载资源

说明:当前类对象的路径定位方式,适合读取与类位于同一包下的资源。

InputStream inputStream = getClass().getResourceAsStream("/config/sample.txt");
  • 以 / 开头则从根路径定位;

  • 相对路径时以类的包路径为基准。

3、使用 Spring 的 ResourceLoader

说明:借助 Spring 提供的通用资源加载抽象,可读取 classpath、file、http 等协议资源。

@Resourceprivate 
ResourceLoader resourceLoader;

4、使用 ResourceUtils.getFile()

说明:用于将 classpath 路径资源转为 File 对象,适合需要文件路径的场景。

File file = ResourceUtils.getFile("classpath:config/sample.txt");

5、使用 ApplicationContext.getResource()

说明:通过上下文注入加载资源,与 ResourceLoader 类似。

@Resourceprivate 
ApplicationContext context;

6、使用 ServletContext.getResourceAsStream()

说明:用于传统 Servlet 模型,从 Web 路径中获取资源文件。

@Resourceprivate 
ServletContext servletContext;

7、使用 Java IO 的 File

说明:适用于读取项目中的真实文件,路径为实际操作系统路径。

File file = new File("src/main/resources/config/sample.txt");

8、使用 Java NIO 的 Paths 和 Files

说明:使用 Java 8 的现代化文件操作接口,线程安全且效率更高。

Path path = Paths.get("src/main/resources/config/sample.txt");

9、使用 Spring 的 ClassPathResource

说明:Spring 原生支持 classpath 路径加载,简单快捷。

ClassPathResource resource = new ClassPathResource("config/sample.txt");
统一完整代码实现示例

我们将在一个 Spring Boot 控制器中统一实现这 9 种方式,以 /resource/read/{method} 接口形式暴露,让你一目了然。

文件路径准备

请在 src/main/resources/config/sample.txt 文件中放置如下测试内容:

这是一个用于演示读取 resources 文件的示例文本。

控制器实现:com.icoderoad.resources.controller.ResourceReadController.java

package com.icoderoad.resources.controller;import jakarta.annotation.Resource;
import jakarta.servlet.ServletContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Controller;
import org.springframework.util.FileCopyUtils;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.*;import java.io.*;
import java.nio.file.*;
import java.util.HashMap;
import java.util.Map;@RestController
@RequestMapping("/resource/read")
public class ResourceReadController {@Autowiredprivate ResourceLoader resourceLoader;@Autowiredprivate ApplicationContext applicationContext;@Autowiredprivate ServletContext servletContext;private final String filePath = "config/sample.txt";@GetMapping("/{method}")public Map<String, Object> readFile(@PathVariable String method) {Map<String, Object> result = new HashMap<>();try {String content = switch (method) {case "classloader" -> readByClassLoader();case "class" -> readByClass();case "loader" -> readByResourceLoader();case "utils" -> readByResourceUtils();case "context" -> readByApplicationContext();case "servlet" -> readByServletContext();case "file" -> readByFile();case "nio" -> readByNio();case "classpath" -> readByClassPathResource();default -> "Unsupported method!";};result.put("method", method);result.put("content", content);} catch (Exception e) {result.put("error", e.getMessage());}return result;}private String readByClassLoader() throws IOException {try (InputStream in = getClass().getClassLoader().getResourceAsStream(filePath)) {return streamToString(in);}}private String readByClass() throws IOException {try (InputStream in = getClass().getResourceAsStream("/" + filePath)) {return streamToString(in);}}private String readByResourceLoader() throws IOException {org.springframework.core.io.Resource resource = resourceLoader.getResource("classpath:" + filePath);try (InputStream in = resource.getInputStream()) {return streamToString(in);}}private String readByResourceUtils() throws IOException {File file = ResourceUtils.getFile("classpath:" + filePath);try (InputStream in = new FileInputStream(file)) {return streamToString(in);}}private String readByApplicationContext() throws IOException {org.springframework.core.io.Resource resource = applicationContext.getResource("classpath:" + filePath);try (InputStream in = resource.getInputStream()) {return streamToString(in);}}private String readByServletContext() throws IOException {// 仅适用于传统部署模式,如 war 包放入 Tomcat 时try (InputStream in = servletContext.getResourceAsStream("/WEB-INF/classes/" + filePath)) {return streamToString(in);}}private String readByFile() throws IOException {File file = new File("src/main/resources/" + filePath);try (InputStream in = new FileInputStream(file)) {return streamToString(in);}}private String readByNio() throws IOException {Path path = Paths.get("src/main/resources/" + filePath);try (InputStream in = Files.newInputStream(path)) {return streamToString(in);}}private String readByClassPathResource() throws IOException {ClassPathResource resource = new ClassPathResource(filePath);try (InputStream in = resource.getInputStream()) {return streamToString(in);}}private String streamToString(InputStream in) throws IOException {return new String(FileCopyUtils.copyToByteArray(in));}
}

 使用方式说明

请求路径对应加载方式
/resource/read/classloaderClassLoader.getResourceAsStream()
/resource/read/classClass.getResourceAsStream()
/resource/read/loaderResourceLoader
/resource/read/utilsResourceUtils.getFile()
/resource/read/contextApplicationContext.getResource()
/resource/read/servletServletContext.getResourceAsStream()
/resource/read/filenew File() + FileInputStream
/resource/read/nioPaths + Files
/resource/read/classpathClassPathResource

总结

在本文中,我们不仅系统讲解了 Spring Boot 项目中读取 resources 目录下文件的 9 大方式,还构建了一个完整的统一控制器 Demo,集中展示它们在实际项目中的使用方式。你可以根据以下建议进行选择:

  • 推荐方式(通用性 + 简洁性)

    • ClassLoader.getResourceAsStream()

    • ClassPathResource

    • ResourceLoader

  • 特定场景方式(依赖文件路径、Web环境)

    • File / Paths / ServletContext

理解并熟练掌握这些方式,将极大提高你在 Spring Boot 项目中处理静态资源的灵活性与稳定性,特别是在构建插件机制、配置中心、文件服务等系统中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/88032.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/88032.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/88032.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

力扣-1143.最长公共子序列

题目描述 给定两个字符串 text1 和 text2&#xff0c;返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 &#xff0c;返回 0 。 一个字符串的 子序列 是指这样一个新的字符串&#xff1a;它是由原字符串在不改变字符的相对顺序的情况下删除某些字符&#xf…

《算法笔记》之二(笔记)

1. vector&#xff1a; 1.定义&#xff1a;“变长数组”&#xff08;长度依据需要而自动改变&#xff0c;节省空间&#xff0c;避免普通数组超内存&#xff09; 代码定义&#xff1a;vector < typename > name; 注&#xff1a;&#xff08;注意理解&#xff09; vecto…

PROFIBUS DP 转 EtherCAT 网关:冶金自动化高效协同的基石

在冶金行业高炉、连铸、轧钢等复杂场景中&#xff0c;生产设备往往跨越不同时代。许多关键产线仍依赖西门子PLC为核心的PROFIBUS DP网络&#xff0c;而新型伺服驱动器、机器人手臂则普遍采用高性能EtherCAT接口。如何实现新旧系统的无缝集成&#xff1f;JH-PB-ECT疆鸿智能PROFI…

开发云数据库

1、云数据库概述 云数据库是一款端云协同的数据库产品&#xff0c;是AGC云开发&#xff08;AGC Serverless&#xff09;关键服务之一&#xff0c;为AGC构建了MBaas&#xff08;Mobile Backend as a Service&#xff0c;移动后端即服务&#xff09;能力。云数据库提供了端云数据…

IEEE使用遇到的问题

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、如何在已知期刊中查找自己方向的论文 前言 IEEE 使用相关问题记录 一、如何在已知期刊中查找自己方向的论文 比如在IEEE Transactions on Visualization …

深入解析C#数组协变与克隆机制

—— 值类型与引用类型的内存行为差异 &#x1f50d; 一、数组协变&#xff08;Array Covariance&#xff09; 核心条件&#xff1a; 仅适用于引用类型数组被赋值对象与数组基类型需存在隐式/显式转换关系 class Animal {} class Dog : Animal {}Animal[] animals new Dog…

零散问题一

1.函数重载的原理 名称修饰&#xff08;Name Mangling&#xff09; 作用&#xff1a;编译器在编译时对函数名进行编码&#xff0c;生成唯一的内部标识符&#xff0c;使得同名函数能通过参数列表的差异被区分。示例&#xff1a; void func(int a); // 修饰后可能为 _Z4funcivo…

React Native【详解】内置 API

屏幕 Dimensions 获取屏幕信息 import { Dimensions } from "react-native"; export default function demo() {const { width, height, scale, fontScale } Dimensions.get("window");console.log(width, height, scale, fontScale); }参数为 window 时…

Selenium自动化测试常见的异常处理

在软件开发和测试领域,Selenium作为一种广泛使用的自动化测试工具,扮演着至关重要的角色。随着自动化测试的不断普及,如何在测试过程中有效捕获并处理异常,成为了每个测试工程师必须掌握的技能。本文旨在深入探讨Selenium异常处理的方法,通过丰富的案例和代码,帮助新手朋…

企业级安全实践:SSL 加密与权限管理(二)

权限管理&#xff1a;企业数据的守护者 权限管理的基本概念与重要性 权限管理&#xff0c;是指根据系统设置的安全规则或策略&#xff0c;用户可以访问且仅能访问自己被授权的资源&#xff0c;不多不少 。它是企业信息安全体系的重要组成部分&#xff0c;旨在确保只有授权的人…

AMAT P5000 CVDFDT CVDMAINT Precision 5000 Mark 操作 电气原理 PCB图 电路图等

AMAT P5000 CVDFDT CVDMAINT Precision 5000 Mark 操作 电气原理 PCB图 电路图等

深入浅出:语言模型中的“自回归生成”是什么?

在当今大语言模型&#xff08;LLM&#xff09;如 ChatGPT、GPT-4、文心一言、通义千问等风靡的时代&#xff0c;“自回归生成”是驱动它们流畅对话、创作文本的核心引擎。 理解它是深入掌握LLM工作原理的关键一步。本文将用清晰易懂的语言&#xff0c;结合实例&#xff0c;为你…

LLMs基础学习(八)强化学习专题(5)

LLMs基础学习&#xff08;八&#xff09;强化学习专题&#xff08;5&#xff09; 文章目录 LLMs基础学习&#xff08;八&#xff09;强化学习专题&#xff08;5&#xff09;重要性采样&#xff08;Importance Sampling&#xff09;权重计算逻辑两种实现形式使用注意事项 PPO 与…

深入理解“回调地狱“(Callback Hell)

"回调地狱"是异步编程中常见的问题&#xff0c;指由于过多嵌套的回调函数导致的代码难以理解和维护的情况。 一、什么是回调地狱 基本概念 回调地狱(Callback Hell/Pyramid of Doom)是指&#xff1a; 多层嵌套的回调函数形成的代码结构 代码向右缩进越来越深&…

Oracle 的 TCP.SEND_TIMEOUT 参数

Oracle 的 TCP.SEND_TIMEOUT 参数 一 参数基本概念 TCP.SEND_TIMEOUT 是 Oracle Net Services 中的一个重要参数&#xff0c;用于控制 TCP 数据发送操作的最长等待时间。 二 关键特性 特性说明参数类型sqlnet.ora 配置文件参数默认值none (无超时限制)单位ms, sec, min, 默…

[Nginx] 配置中的sendfile参数详解:从传统 IO 到零拷贝的性能优化

一、sendfile 是什么&#xff1f; sendfile 是 Nginx 中一个关键的配置参数&#xff0c;用于控制是否使用操作系统提供的 sendfile() 系统调用来传输文件。 sendfile on;&#xff1a;启用零拷贝技术&#xff0c;直接由内核将文件发送到网络。sendfile off;&#xff1a;使用传统…

(LeetCode 每日一题) 2138. 将字符串拆分为若干长度为 k 的组 (字符串、模拟)

题目&#xff1a;2138. 将字符串拆分为若干长度为 k 的组 思路&#xff1a;字符串模拟&#xff0c;时间复杂度0(n)。 C版本&#xff1a; class Solution { public:vector<string> divideString(string s, int k, char fill) {vector<string> v;int ns.size();for…

C++法则1:在 C++ 中,所有的具名变量都是左值,即使它们的类型是右值引用。

看下面例子&#xff1a; test(0)调用的是函数是&#xff1a; template<typename T> void test(T&& t) {std::cout << "右值引用" << std::endl; }test(n)调用的是函数是&#xff1a; template<typename T> void test(T& t) {st…

python如何使用正则提取文章所有形容词

在Python中使用正则表达式提取文章中的形容词需要结合语言特性处理。以下是分步解决方案&#xff1a; 英文场景解决方案&#xff08;推荐使用专业NLP库&#xff09;&#xff1a; import re import nltk nltk.download(averaged_perceptron_tagger) # 首次使用需要下载text …

低代码平台的数据归集及治理

低代码平台或无码平台&#xff0c;在建表单的时候&#xff0c;都是每一个表单一个json的格式文件&#xff0c;存储在Nosql数据库中。在开发的过程中&#xff0c;有以下主要的需求 1、json格式实时的转为关系数据库的格式&#xff0c;存入到关系数据库中 需要在流程结束的时候&…