0
# Resource Management
1
2
Spring Core provides a comprehensive abstraction for accessing resources from various sources including classpath, file system, URLs, and in-memory data. This unified API simplifies resource handling across different deployment scenarios.
3
4
## Core Resource Interface
5
6
The `Resource` interface provides the fundamental abstraction for all resource types.
7
8
**Resource Interface**
9
```java { .api }
10
public interface Resource extends InputStreamSource {
11
boolean exists();
12
default boolean isReadable();
13
default boolean isOpen();
14
default boolean isFile();
15
16
URL getURL() throws IOException;
17
URI getURI() throws IOException;
18
File getFile() throws IOException;
19
default ReadableByteChannel readableChannel() throws IOException;
20
21
long contentLength() throws IOException;
22
long lastModified() throws IOException;
23
24
Resource createRelative(String relativePath) throws IOException;
25
String getFilename();
26
String getDescription();
27
28
// From InputStreamSource
29
InputStream getInputStream() throws IOException;
30
}
31
32
public interface InputStreamSource {
33
InputStream getInputStream() throws IOException;
34
}
35
```
36
37
**Writable Resource Extension**
38
```java { .api }
39
public interface WritableResource extends Resource {
40
default boolean isWritable();
41
OutputStream getOutputStream() throws IOException;
42
default WritableByteChannel writableChannel() throws IOException;
43
}
44
```
45
46
**Usage Examples**
47
```java
48
// Basic resource operations
49
Resource resource = new ClassPathResource("config/application.properties");
50
51
// Check resource existence and properties
52
if (resource.exists() && resource.isReadable()) {
53
long size = resource.contentLength();
54
long modified = resource.lastModified();
55
String filename = resource.getFilename(); // "application.properties"
56
57
// Read content
58
try (InputStream input = resource.getInputStream()) {
59
Properties props = new Properties();
60
props.load(input);
61
}
62
}
63
64
// Get file system representation
65
if (resource.isFile()) {
66
File file = resource.getFile();
67
Path path = file.toPath();
68
}
69
70
// Create relative resources
71
Resource siblingResource = resource.createRelative("../logging/logback.xml");
72
```
73
74
## Resource Implementations
75
76
Spring provides several concrete `Resource` implementations for different source types.
77
78
**ClassPath Resources**
79
```java { .api }
80
public class ClassPathResource extends AbstractFileResolvingResource {
81
public ClassPathResource(String path);
82
public ClassPathResource(String path, Class<?> clazz);
83
public ClassPathResource(String path, ClassLoader classLoader);
84
85
public final String getPath();
86
public final ClassLoader getClassLoader();
87
88
@Override
89
public boolean exists();
90
@Override
91
public InputStream getInputStream() throws IOException;
92
@Override
93
public URL getURL() throws IOException;
94
@Override
95
public String getDescription();
96
}
97
```
98
99
**File System Resources**
100
```java { .api }
101
public class FileSystemResource extends AbstractResource implements WritableResource {
102
public FileSystemResource(String path);
103
public FileSystemResource(File file);
104
public FileSystemResource(Path filePath);
105
106
public final String getPath();
107
public final File getFile();
108
109
@Override
110
public boolean exists();
111
@Override
112
public boolean isReadable();
113
@Override
114
public InputStream getInputStream() throws IOException;
115
@Override
116
public boolean isWritable();
117
@Override
118
public OutputStream getOutputStream() throws IOException;
119
@Override
120
public String getDescription();
121
}
122
```
123
124
**URL Resources**
125
```java { .api }
126
public class UrlResource extends AbstractFileResolvingResource {
127
public UrlResource(URL url);
128
public UrlResource(String location) throws MalformedURLException;
129
public UrlResource(String protocol, String location) throws MalformedURLException;
130
131
@Override
132
public InputStream getInputStream() throws IOException;
133
@Override
134
public URL getURL();
135
@Override
136
public URI getURI() throws IOException;
137
@Override
138
public boolean exists();
139
@Override
140
public String getDescription();
141
}
142
```
143
144
**Byte Array Resources**
145
```java { .api }
146
public class ByteArrayResource extends AbstractResource {
147
public ByteArrayResource(byte[] byteArray);
148
public ByteArrayResource(byte[] byteArray, String description);
149
150
public final byte[] getByteArray();
151
152
@Override
153
public boolean exists();
154
@Override
155
public long contentLength();
156
@Override
157
public InputStream getInputStream();
158
@Override
159
public String getDescription();
160
}
161
```
162
163
**Usage Examples**
164
```java
165
// ClassPath resources
166
Resource configResource = new ClassPathResource("application.yml");
167
Resource templatesDir = new ClassPathResource("templates/", MyClass.class);
168
Resource libResource = new ClassPathResource("lib/helper.jar", classLoader);
169
170
// File system resources
171
Resource dataFile = new FileSystemResource("/data/users.csv");
172
Resource tempFile = new FileSystemResource(Files.createTempFile("temp", ".txt"));
173
174
// Write to file system resource
175
if (dataFile instanceof WritableResource writable && writable.isWritable()) {
176
try (OutputStream output = writable.getOutputStream()) {
177
output.write("New data".getBytes());
178
}
179
}
180
181
// URL resources
182
Resource remoteConfig = new UrlResource("https://config.example.com/app.properties");
183
Resource jarResource = new UrlResource("jar:file:/app/lib/data.jar!/config.xml");
184
185
// Byte array resources (useful for testing)
186
byte[] data = "Test configuration".getBytes();
187
Resource memoryResource = new ByteArrayResource(data, "test-config");
188
```
189
190
## Resource Loading
191
192
Spring provides a strategy-based approach for loading resources with support for location patterns.
193
194
**ResourceLoader Interface**
195
```java { .api }
196
public interface ResourceLoader {
197
String CLASSPATH_URL_PREFIX = "classpath:";
198
199
Resource getResource(String location);
200
ClassLoader getClassLoader();
201
}
202
203
public class DefaultResourceLoader implements ResourceLoader {
204
public DefaultResourceLoader();
205
public DefaultResourceLoader(ClassLoader classLoader);
206
207
public void setClassLoader(ClassLoader classLoader);
208
209
@Override
210
public ClassLoader getClassLoader();
211
@Override
212
public Resource getResource(String location);
213
214
public void addProtocolResolver(ProtocolResolver protocolResolver);
215
public Collection<ProtocolResolver> getProtocolResolvers();
216
public void clearProtocolResolvers();
217
218
protected Resource getResourceByPath(String path);
219
}
220
```
221
222
**Pattern-Based Resource Loading**
223
```java { .api }
224
public interface ResourcePatternResolver extends ResourceLoader {
225
String CLASSPATH_ALL_URL_PREFIX = "classpath*:";
226
227
Resource[] getResources(String locationPattern) throws IOException;
228
}
229
230
public class PathMatchingResourcePatternResolver
231
implements ResourcePatternResolver, Ordered {
232
233
public PathMatchingResourcePatternResolver();
234
public PathMatchingResourcePatternResolver(ResourceLoader resourceLoader);
235
public PathMatchingResourcePatternResolver(ClassLoader classLoader);
236
237
public void setPathMatcher(PathMatcher pathMatcher);
238
public PathMatcher getPathMatcher();
239
240
@Override
241
public Resource getResource(String location);
242
@Override
243
public Resource[] getResources(String locationPattern) throws IOException;
244
245
@Override
246
public int getOrder();
247
}
248
```
249
250
**Protocol Resolver Extension**
251
```java { .api }
252
@FunctionalInterface
253
public interface ProtocolResolver {
254
Resource resolve(String location, ResourceLoader resourceLoader);
255
}
256
```
257
258
**Usage Examples**
259
```java
260
// Basic resource loading
261
ResourceLoader loader = new DefaultResourceLoader();
262
263
// Load from different sources based on prefix
264
Resource classpathResource = loader.getResource("classpath:config.properties");
265
Resource fileResource = loader.getResource("file:./data.txt");
266
Resource urlResource = loader.getResource("https://example.com/config.json");
267
268
// Pattern-based loading
269
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
270
271
// Load all matching resources from classpath
272
Resource[] configFiles = resolver.getResources("classpath*:config/*.properties");
273
Resource[] xmlFiles = resolver.getResources("classpath:spring/**/*.xml");
274
Resource[] allJars = resolver.getResources("classpath*:lib/*.jar");
275
276
// Process multiple resources
277
for (Resource resource : configFiles) {
278
if (resource.exists()) {
279
Properties props = new Properties();
280
try (InputStream input = resource.getInputStream()) {
281
props.load(input);
282
}
283
System.out.println("Loaded: " + resource.getDescription());
284
}
285
}
286
287
// Custom protocol resolver
288
loader.addProtocolResolver((location, resourceLoader) -> {
289
if (location.startsWith("custom:")) {
290
String path = location.substring(7);
291
return new FileSystemResource("/custom/path/" + path);
292
}
293
return null;
294
});
295
296
Resource customResource = loader.getResource("custom:myfile.txt");
297
```
298
299
## Resource Utilities
300
301
**Resource Utility Classes**
302
```java { .api }
303
public abstract class ResourceUtils {
304
public static final String CLASSPATH_URL_PREFIX = "classpath:";
305
public static final String FILE_URL_PREFIX = "file:";
306
public static final String JAR_URL_PREFIX = "jar:";
307
public static final String WAR_URL_PREFIX = "war:";
308
309
public static boolean isUrl(String resourceLocation);
310
public static URL getURL(String resourceLocation) throws FileNotFoundException;
311
public static File getFile(String resourceLocation) throws FileNotFoundException;
312
public static File getFile(URL resourceUrl) throws FileNotFoundException;
313
public static File getFile(URI resourceUri) throws FileNotFoundException;
314
315
public static boolean isFileURL(URL url);
316
public static boolean isJarURL(URL url);
317
public static boolean isJarFileURL(URL url);
318
319
public static URL extractJarFileURL(URL jarUrl) throws MalformedURLException;
320
public static URL extractArchiveURL(URL jarUrl) throws MalformedURLException;
321
322
public static URI toURI(URL url) throws URISyntaxException;
323
public static URI toURI(String location) throws URISyntaxException;
324
}
325
```
326
327
**Usage Examples**
328
```java
329
// Check resource location types
330
boolean isUrl = ResourceUtils.isUrl("https://example.com/file.txt"); // true
331
boolean isClasspath = ResourceUtils.isUrl("classpath:config.xml"); // false
332
333
// Get File objects from resource locations
334
File configFile = ResourceUtils.getFile("classpath:application.properties");
335
File dataFile = ResourceUtils.getFile("file:/data/users.csv");
336
337
// Work with JAR URLs
338
URL jarUrl = new URL("jar:file:/app/lib/mylib.jar!/config.xml");
339
boolean isJar = ResourceUtils.isJarURL(jarUrl); // true
340
URL jarFileUrl = ResourceUtils.extractJarFileURL(jarUrl); // file:/app/lib/mylib.jar
341
```
342
343
## Context Resource Interface
344
345
**Context-Aware Resources**
346
```java { .api }
347
public interface ContextResource extends Resource {
348
String getPathWithinContext();
349
}
350
351
public interface HttpResource extends Resource {
352
HttpHeaders getResponseHeaders();
353
}
354
```
355
356
**File-Based Resource Extensions**
357
```java { .api }
358
public abstract class AbstractFileResolvingResource extends AbstractResource {
359
@Override
360
public boolean exists();
361
@Override
362
public boolean isReadable();
363
@Override
364
public boolean isFile();
365
@Override
366
public File getFile() throws IOException;
367
@Override
368
public ReadableByteChannel readableChannel() throws IOException;
369
@Override
370
public long contentLength() throws IOException;
371
@Override
372
public long lastModified() throws IOException;
373
374
protected File getFileForLastModifiedCheck() throws IOException;
375
protected boolean isFile(URI uri);
376
protected File getFile(URI uri) throws IOException;
377
protected File getFile(URL url) throws IOException;
378
}
379
380
public abstract class AbstractResource implements Resource {
381
@Override
382
public boolean exists();
383
@Override
384
public boolean isReadable();
385
@Override
386
public boolean isOpen();
387
@Override
388
public boolean isFile();
389
@Override
390
public URL getURL() throws IOException;
391
@Override
392
public URI getURI() throws IOException;
393
@Override
394
public File getFile() throws IOException;
395
@Override
396
public ReadableByteChannel readableChannel() throws IOException;
397
@Override
398
public long contentLength() throws IOException;
399
@Override
400
public long lastModified() throws IOException;
401
@Override
402
public Resource createRelative(String relativePath) throws IOException;
403
@Override
404
public String getFilename();
405
406
// Utility methods
407
public String toString();
408
public boolean equals(Object other);
409
public int hashCode();
410
}
411
```
412
413
## Advanced Resource Features
414
415
**Input Stream Source Chain**
416
```java { .api }
417
public class InputStreamResource extends AbstractResource {
418
public InputStreamResource(InputStream inputStream);
419
public InputStreamResource(InputStream inputStream, String description);
420
421
@Override
422
public String getDescription();
423
@Override
424
public InputStream getInputStream() throws IOException;
425
@Override
426
public boolean equals(Object other);
427
@Override
428
public int hashCode();
429
}
430
```
431
432
**Encoded Resources**
433
```java { .api }
434
public class EncodedResource implements InputStreamSource {
435
public EncodedResource(Resource resource);
436
public EncodedResource(Resource resource, String encoding);
437
public EncodedResource(Resource resource, Charset charset);
438
439
public final Resource getResource();
440
public final String getEncoding();
441
public final Charset getCharset();
442
443
public boolean requiresReader();
444
public Reader getReader() throws IOException;
445
@Override
446
public InputStream getInputStream() throws IOException;
447
}
448
```
449
450
**Usage Examples**
451
```java
452
// Work with encoded resources
453
Resource xmlResource = new ClassPathResource("data/users.xml");
454
EncodedResource encodedXml = new EncodedResource(xmlResource, "UTF-8");
455
456
// Read as character stream
457
try (Reader reader = encodedXml.getReader()) {
458
// Parse XML with proper encoding
459
}
460
461
// Input stream resource (useful for wrapping existing streams)
462
InputStream dataStream = getDataFromSomewhere();
463
Resource streamResource = new InputStreamResource(dataStream, "external-data");
464
465
// Use in Spring configurations
466
@Bean
467
public Properties applicationProperties() throws IOException {
468
Properties props = new Properties();
469
Resource resource = new ClassPathResource("application.properties");
470
props.load(resource.getInputStream());
471
return props;
472
}
473
```
474
475
## Resource Pattern Matching
476
477
**Path Matcher Interface**
478
```java { .api }
479
public interface PathMatcher {
480
boolean isPattern(String path);
481
boolean match(String pattern, String path);
482
boolean matchStart(String pattern, String path);
483
String extractPathWithinPattern(String pattern, String path);
484
Map<String, String> extractUriTemplateVariables(String pattern, String path);
485
Comparator<String> getPatternComparator(String path);
486
String combine(String pattern1, String pattern2);
487
}
488
489
public class AntPathMatcher implements PathMatcher {
490
public static final String DEFAULT_PATH_SEPARATOR = "/";
491
492
public AntPathMatcher();
493
public AntPathMatcher(String pathSeparator);
494
495
public void setPathSeparator(String pathSeparator);
496
public void setCaseSensitive(boolean caseSensitive);
497
public void setTrimTokens(boolean trimTokens);
498
public void setCachePatterns(boolean cachePatterns);
499
500
@Override
501
public boolean isPattern(String path);
502
@Override
503
public boolean match(String pattern, String path);
504
@Override
505
public boolean matchStart(String pattern, String path);
506
@Override
507
public String extractPathWithinPattern(String pattern, String path);
508
@Override
509
public Map<String, String> extractUriTemplateVariables(String pattern, String path);
510
@Override
511
public Comparator<String> getPatternComparator(String path);
512
@Override
513
public String combine(String pattern1, String pattern2);
514
}
515
```
516
517
**Usage Examples**
518
```java
519
// Pattern matching with AntPathMatcher
520
PathMatcher matcher = new AntPathMatcher();
521
522
// Test patterns
523
boolean matches1 = matcher.match("*.txt", "readme.txt"); // true
524
boolean matches2 = matcher.match("/config/**/*.xml", "/config/prod/db.xml"); // true
525
boolean matches3 = matcher.match("/api/{version}/users", "/api/v1/users"); // true
526
527
// Extract path variables
528
Map<String, String> variables = matcher.extractUriTemplateVariables(
529
"/users/{userId}/posts/{postId}",
530
"/users/123/posts/456"
531
);
532
// Returns: {userId=123, postId=456}
533
534
// Extract path within pattern
535
String extracted = matcher.extractPathWithinPattern(
536
"/static/**",
537
"/static/css/style.css"
538
);
539
// Returns: "css/style.css"
540
541
// Combine patterns
542
String combined = matcher.combine("/api/**", "*.json"); // "/api/**/*.json"
543
```
544
545
This comprehensive resource management system provides the foundation for Spring's configuration loading, template resolution, static resource serving, and many other framework features that need to access resources from various sources in a consistent manner.