概要
Spring FrameworkのResourceインターフェースと実装クラスをを使ったリソースファイルのアクセス方法をおさらいしたときのメモです。
環境
- Windows 10 Professional 1909
- OpenJDK 13
- Spring Boot 2.2.1
参考
- [Core Technologies - 2. Resources] (https://docs.spring.io/spring/docs/5.2.1.RELEASE/spring-framework-reference/core.html#resources)
- [Package org.springframework.core.io] (https://docs.spring.io/spring/docs/5.2.1.RELEASE/javadoc-api/)
[Resource] (https://docs.spring.io/spring/docs/5.2.1.RELEASE/javadoc-api/org/springframework/core/io/Resource.html)
Since 28.12.2003
Interface for a resource descriptor that abstracts from the actual type of underlying resource, such as a file or class path resource.
Resourceインターフェースのインスタンスを取得する方法には
- 実装クラスを使用する
-
ResourceLoader
を使用する -
@Value
アノテーションを使用する
などがあります。
実装クラスを使用する方法
リソースファイルのロケーションに応じて適切なResourceインタフェースの実装クラスを使用する方法です。
たとえば、クラスパス内のリソースにアクセスするためのClassPathResource
、ネットワーク上のリソースにアクセスするためのUrlResource
、ファイルシステム上のリソースにアクセスするためのFileUrlResource
があります。
[ClassPathResource] (https://docs.spring.io/spring/docs/5.2.1.RELEASE/javadoc-api/org/springframework/core/io/ClassPathResource.html)
Since 28.12.2003
Resource implementation for class path resources. Uses either a given ClassLoader or a given Class for loading resources.
コンストラクタ |
---|
ClassPathResource(String path) |
ClassPathResource(String path, Class> clazz) |
ClassPathResource(String path, ClassLoader classLoader) |
コード
Resource resource = new ClassPathResource("config/app.properties");
ResourceインタフェースはInputStreamSource
インタフェースを継承しているのでgetInputStreamメソッドで、リソースファイルのInputStream
を取得することができます。
String read(Resource resource) {
try (InputStream in = resource.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8))) {
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
return sb.toString();
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
なお、ResourceインタフェースはgetFileメソッドもあるので、以下のように記述することができますが、リソースがクラスパス内やネットワーク上にある場合は例外をスローするので、通常はリソースファイルがファイルシステム上にある場合に限って使った方がいいと思います。
String read(Resource resource) {
try {
return Files.readString(resource.getFile().toPath());
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
[UrlResource] (https://docs.spring.io/spring/docs/5.2.1.RELEASE/javadoc-api/org/springframework/core/io/UrlResource.html)
Since 28.12.2003
Resource implementation for java.net.URL locators. Supports resolution as a URL and also as a File in case of the "file:" protocol.
コンストラクタ |
---|
UrlResource(String path) |
UrlResource(String protocol, String location) |
UrlResource(String protocol, String location, String fragment) |
UrlResource(java.net.URI uri) |
UrlResource(java.net.URL url) |
コード
Resource urlResource = new UrlResource("http://localhost:8887/config/app.properties");
[FileUrlResource] (https://docs.spring.io/spring/docs/5.2.1.RELEASE/javadoc-api/org/springframework/core/io/FileUrlResource.html)
Since 5.0.2
Subclass of UrlResource which assumes file resolution, to the degree of implementing the WritableResource interface for it. This resource variant also caches resolved File handles from getFile().
コンストラクタ |
---|
FileUrlResource(String location) |
FileUrlResource(java.net.URL url) |
コード
Resource fileUrlResource = new FileUrlResource("c://var//config/app.properties");
ResourceLoaderを使用する方法
Since 10.03.2004
Strategy interface for loading resources (e.. class path or file system resources). An ApplicationContext is required to provide this functionality, plus extended ResourcePatternResolver support.
DefaultResourceLoader is a standalone implementation that is usable outside an ApplicationContext, also used by ResourceEditor.
Spring Bootでは、ResourceLoaderにはAnnotationConfigServletWebServerApplicationContext
クラスのインスタンスが注入されます。(このクラスはSpring Bootプロジェクトにあります)
@Autowired
private ResourceLoader resourceLoader;
// org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext
classpath
classpath:
から始める書き方をするとClassPathResource
クラスのインスタンスが注入されます。
Resource resource = resourceLoader.getResource("classpath:config/app.properties");
// org.springframework.core.io.ClassPathResource
url
httpスキームで記述するとUrlResource
クラスのインスタンスが注入されます。
Resource resource = resourceLoader.getResource("http://localhost:8887/config/app.properties");
// org.springframework.core.io.UrlResource
file
[fileスキーム] (https://tools.ietf.org/html/rfc8089)で記述すると`FileUrlResource`クラスのインスタンスが注入されます。
Resource resource = resourceLoader.getResource("file:///c://config/app.properties");
// org.springframework.core.io.FileUrlResource
@Value
アノテーションを使用する方法
Valueアノテーションの値により、Spring Frameworkが適切な実装クラスのインスタンスを注入してくれます。
アノテーションに記述する値のフォーマットはResourceLoaderと同じです。
classpath
@Value("classpath:config/app.properties")
private Resource classpathResource;
// org.springframework.core.io.ClassPathResource
url
@Value("http://localhost:8887/config/app.properties")
private Resource urlResource;
// org.springframework.core.io.UrlResource
file
@Value("file:///c://config/app.properties")
private Resource fileUrlResource;
// org.springframework.core.io.FileUrlResource
[ResourceUtils] (https://docs.spring.io/spring/docs/5.2.1.RELEASE/javadoc-api/org/springframework/util/ResourceUtils.html)を使用する方法
Since 1.1.5
Utility methods for resolving resource locations to files in the file system. Mainly for internal use within the framework.
APIドキュメントに書かれている通り、主にSpring Framework内部で使用するためのユーティリティークラスです。アプリケーション側で使ってはいけないという記述はありませんが、あくまでもフレームワーク内での使用を目的としているので利用には留意が必要です。
classpath
File file = ResourceUtils.getFile("classpath:config/app.properties");
url
URL url = ResourceUtils.getURL("http://localhost:8887/config/app.properties");
file
File file = ResourceUtils.getFile("file:///c://var//config/app.properties");
[StreamUtils] (https://docs.spring.io/spring/docs/5.2.1.RELEASE/javadoc-api/org/springframework/util/StreamUtils.html)
Since 3.2.2
Simple utility methods for dealing with streams. The copy methods of this class are similar to those defined in FileCopyUtils except that all affected streams are left open when done. All copy methods use a block size of 4096 bytes.
Mainly for use within the framework, but also useful for application code.
Spring Frameworkにはストリームを処理するユーティリティクラスもあります。このクラスのcopyToStringメソッドを使うと下記のようにコードを簡略化できます。
String data = StreamUtils.copyToString(resource.getInputStream(), StandardCharsets.UTF_8);