Spring Resources

Last update: 2024-01-30 20:15:57 +0800 +0800
Available translations: 日本語 / 中文(简体) / 中文(繁體)

org.springframework.core.io.Resource gives Spring APIs one handle for content that may reside in a file, classpath entry, URL, servlet context, byte array, or already-open stream. The abstraction describes access capabilities; it does not make every resource seekable, repeatable, writable, or backed by a file.

The Resource Contract #

Resource extends InputStreamSource. getInputStream() is the fundamental operation, while methods such as exists(), isReadable(), isOpen(), isFile(), contentLength(), lastModified(), and getDescription() expose capabilities or metadata.

Important implementations include:

  • ClassPathResource for class-loader or class-relative entries;
  • FileSystemResource and PathResource for filesystem content;
  • UrlResource for URLs supported by the JVM;
  • ServletContextResource for web-application paths;
  • ByteArrayResource for repeatable in-memory bytes; and
  • InputStreamResource for an already-open, normally single-use stream.

Callers own every stream returned by getInputStream() and must close it. isOpen() is especially important: an InputStreamResource wraps an open handle and cannot safely be read repeatedly, while file and byte-array resources can open a fresh stream for each call.

Loading and Relative Resolution #

ResourceLoader.getResource(String) converts a location into one resource. Every ApplicationContext is a resource loader. Prefixes select explicit semantics:

  • classpath:com/example/report.html selects a classpath resource.
  • file:/srv/app/report.html selects a filesystem URL.
  • https://example.net/schema.json selects a URL resource.

An unprefixed location is context-relative. A ClassPathXmlApplicationContext interprets it as a classpath location, FileSystemXmlApplicationContext as a filesystem location, and a web application context as a servlet-context location. Library code should request a Resource or ResourceLoader rather than assume one default.

ResourcePatternResolver extends loading to location patterns and multiple matches. classpath*: searches all matching classpath roots; Ant-style wildcards apply through pattern resolution, not through the single-resource ResourceLoader contract.

Injecting Resources #

Spring can convert a location string to Resource using the surrounding application context as the loader:

java
@Component
final class ReportRenderer {
    private final Resource template;

    ReportRenderer(@Value("${report.template:classpath:reports/daily.html}")
                   Resource template) {
        this.template = template;
    }
}

Constructor injection makes the dependency visible and lets a test supply a ByteArrayResource. Inject ResourceLoader when the location varies per operation, and inject Resource[] or a ResourcePatternResolver only when the application intentionally accepts multiple matches.

Existence, Repeatability, and Writing #

exists() is a probe, not a reservation; content can disappear before it is opened. Prefer opening the resource and handling the resulting IOException when correctness depends on access. Metadata operations can also require I/O, and a remote URL can be slow or unavailable.

WritableResource adds isWritable() and getOutputStream(). FileSystemResource and PathResource implement it, while classpath resources inside a packaged JAR do not. Code that writes should require WritableResource rather than downcast based on a location string.

Repeatability depends on the implementation. A parser that needs two passes can buffer a one-shot resource into a ByteArrayResource, with an explicit size limit. APIs should document whether they open once, reopen, retain, or close streams so resource ownership remains unambiguous.

Primary References #

Comments

Read or comment on GitHub (sign-in required to comment)