Mastering Spring’s Resource API: From Resource to ResourceLoader
This article explains Spring's Resource abstraction, its key methods, built‑in implementations, and how to use ResourceLoader, ResourcePatternResolver, and ResourceLoaderAware for flexible resource access in Spring Boot 2.7 applications.
1. Introduction
Java's standard java.net.URL handling is insufficient for many resource access scenarios, especially when resources are obtained from the classpath or ServletContext . Spring provides a richer Resource abstraction to address these gaps.
1.1 Spring Resource Interface
The org.springframework.core.io.Resource interface extends InputStreamSource and defines a set of methods for accessing underlying resources.
<code>public interface Resource extends InputStreamSource {
boolean exists();
boolean isOpen();
boolean isFile();
URL getURL() throws IOException;
URI getURI() throws IOException;
File getFile() throws IOException;
String getFilename();
String getDescription();
}
public interface InputStreamSource {
InputStream getInputStream() throws IOException;
}</code>Key Methods
getInputStream() : Opens the resource and returns a new InputStream for each call; the caller must close it.
exists() : Returns true if the resource physically exists.
isOpen() : Indicates whether the resource represents an open stream handle; most implementations return false except InputStreamResource .
getDescription() : Provides a description used in error messages, typically the full file name or URL.
Note: The Resource abstraction does not replace functionality; it merely wraps existing mechanisms (e.g., UrlResource wraps a URL ).
1.2 Built‑in Resource Implementations
UrlResource : Wraps a java.net.URL to access files, HTTPS, FTP, etc.
ClassPathResource : Loads resources from the classpath using the thread context class loader or a specified class loader.
FileSystemResource : Represents a java.io.File handle; also supports java.nio.file.Path .
PathResource : Uses the java.nio.file.Path API and implements WritableResource .
ServletContextResource : Resolves paths relative to the web application root; supports stream and URL access when the web archive is expanded.
InputStreamResource : Wraps a given InputStream ; returns isOpen() true and should be avoided for repeatable reads.
ByteArrayResource : Wraps a byte array as a resource, creating a ByteArrayInputStream on demand.
2. ResourceLoader Interface
All Spring ApplicationContext implementations also implement ResourceLoader , allowing them to obtain Resource instances. Different context types return different concrete Resource classes.
<code>ApplicationContext context = new ClassPathXmlApplicationContext();
Resource res = context.getResource("app.xml");
System.out.println(res.getClass());
context = new FileSystemXmlApplicationContext();
System.out.println(context.getResource("d:\\1.txt").getClass());
GenericWebApplicationContext ctx = new GenericWebApplicationContext();
ctx.setServletContext(new MockServletContext());
System.out.println(context.getResource("WEB-INF/app.properties").getClass());</code>Typical output shows ClassPathContextResource for classpath resources and FileSystemResource for file‑system resources. In a Spring Boot environment the default context is AnnotationConfigServletWebServerApplicationContext , which returns a ServletContextResource for web‑based resources.
<code>@Resource
private ApplicationContext context;
System.out.println(context.getResource("application.yml"));</code>Result: ServletContext resource [/application.yml]
Resource locations can be prefixed:
Classpath: ctx.getResource("classpath:com/pack/app.properties")
File or HTTP: ctx.getResource("file:///d:/1.txt") or ctx.getResource("http://www.pack.com/1.txt")
Note: Omitting a prefix makes the lookup depend on the specific ApplicationContext implementation.
3. ResourcePatternResolver Interface
This extends ResourceLoader and adds support for location patterns (e.g., Ant‑style paths). The primary implementation is PathMatchingResourcePatternResolver , which can resolve multiple matching resources without requiring an ApplicationContext .
<code>PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource resource = resolver.getResource("file:///d:/1.txt");
System.out.println(resource.getContentAsString(StandardCharsets.UTF_8));
System.out.println(resolver.getResource(ResourcePatternResolver.CLASSPATH_URL_PREFIX + "app.properties").getContentAsString(StandardCharsets.UTF_8));</code>4. ResourceLoaderAware Interface
Components that need direct access to a ResourceLoader can implement ResourceLoaderAware . Spring injects the concrete ApplicationContext (e.g., AnnotationConfigServletWebServerApplicationContext ) as the loader.
<code>@Component
public class ResourceManager implements ResourceLoaderAware {
private ResourceLoader loader;
public Resource getResource(String location) {
return this.loader.getResource(location);
}
@Override
public void setResourceLoader(ResourceLoader resourceLoader) {
this.loader = resourceLoader;
}
}</code>The loader can also be injected via @Autowired , @Resource , or @Inject .
5. Resource Dependency Injection
Static resources can be injected directly without using the loader interfaces.
<code>@RestController
@RequestMapping("/demos")
public class DemoController {
@Value("${pack.images:file:///d:/images/1.png}")
private Resource res;
@GetMapping("/res0")
public void res0(HttpServletResponse response) throws Exception {
response.setContentType("image/png");
StreamUtils.copy(res.getInputStream(), response.getOutputStream());
}
}</code> <code>@Component
public class MyResource {
private final Resource template;
public MyResource(@Value("${pack.path}") Resource template) {
this.template = template;
}
}</code> <code>@Component
public class MyResource {
private final Resource[] template;
public MyResource(@Value("${pack.paths}") Resource[] template) {
this.template = template;
}
}</code>Classpath Prefixes: classpath: returns a single resource and throws an exception if it does not exist; classpath*: returns all matching resources and yields an empty collection when none are found.
Above is the complete content of the article.
Spring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.