在 Spring 中处理资源

本文涉及如何在 Spring 中处理资源,我们将研究各种接口,如 Resource、ResourceLoader 和 ResourceLoaderAware。我们通常不必对 Spring 处理资源的方式进行任何修改。我们将具体学习 Spring 是如何处理资源的。
不要与@Resource 注解混淆。本文是关于 File、URLResources、ServletContext 等资源的。对于 @Resource,请查看相关文章 - Spring 中的 @Autowired、@Resource 和 @Inject 指南。
Spring中的资源接口
Java 提供 java.net.URL 类来处理标准的 URL 资源。但是,它不能从类路径或相对于 ServletContext 等加载资源。 Spring 提供了额外的特性来处理这些资源。
Spring 有一个 Resource 接口,具有更多处理低级资源的能力。 Spring 不仅允许您强大地处理低级资源,而且在其核心中广泛使用资源抽象。
Resource
public interface Resource extends InputStreamSource {
boolean exists();
boolean isOpen();
URL getURL() throws IOException;
File getFile() throws IOException;
Resource createRelative(String relativePath) throws IOException;
String getFilename();
String getDescription();
}
InputStreamSource
public interface InputStreamSource {
InputStream getInputStream() throws IOException;
}
正如您在上面看到的,Resource 接口有几个有用的方法,例如:
exists() - 指示提供的资源是否实际以物理形式存在。
isOpen() – 表示来自 InputStreamSource 的 inputStream 是否打开。如果是这样,它应该在读取操作完成后关闭。
getInputStream() – 从 InputStreamSource 接口返回一个 InputStream。
通常,以下是 Spring 处理的资源类型。它们都实现了 Resource 接口。
- UrlResource
- ClassPathResource
- FileSystemResource
- ServletContextResource
- InputStreamResource
- ByteArrayResource
Spring中的UrlResource
此类实现 Resource 接口并在 java.net.URL 和 java.net.URI 之上添加了额外的功能。您可以使用此类访问 http://、https:// 或 ftp:// 上可用的任何资源。
public class ResourcesExample {
public static void main(String[] args) throws IOException {
Resource urlResource = new UrlResource("https://google.com");
readAndPrint(urlResource.getInputStream());
}
public static void readAndPrint(InputStream stream) throws IOException {
int content = stream.read();
System.out.println("\n============ start ===========");
while (content != -1) {
System.out.print((char)content);
content = stream.read();
}
System.out.println("\n============ End ============");
stream.close();
}
}
Spring中的ClassPathResource
此类表示需要存在于类路径中的资源。在内部,它要么使用线程上下文类加载器,要么使用给定的类加载器来获取资源。
//Fetching sample.md from classpath
Resource classPathResource = new ClassPathResource("sample.md");
readAndPrint(classPathResource.getInputStream());
Spring中的FileSystemResource
此类是 java.io.File 和 java.nio.file.Path 句柄的实现。它支持作为文件和 URL 的解析。这用于从本地系统访问文件/资源。
//Use it with the first example
FileSystemResource fileResource = new FileSystemResource("PathToFile/filename");
readAndPrint(fileResource.getInputStream());
Spring中的ServletContextResource
此资源是 Spring MVC 应用程序中 ServletContext 的实现。它解释 Web 应用程序根目录中的相对路径。
Spring中的InputStreamResource
它是给定 InputStream 的资源实现。仅当没有特定的资源实现适用时才使用。尽可能使用 ByteArrayResource 或任何基于文件的资源实现。
Spring中的ByteArrayResource
这是给定字节数组的资源实现。它为给定的字节数组创建一个 ByteArrayInputStream。它对于从任何给定的字节数组加载内容很有用,而不必求助于单一使用的 InputStreamResource。
使用 ResourceLoader 接口
Spring 中的 ResourceLoader 接口旨在由可以加载和返回 Resource 实例的对象实现。所有应用程序上下文都实现了这个接口。
public interface ResourceLoader {
Resource getResource(String location);
}
Spring 中有多种 ResourceLoader 的实现。这些是 DefaultResourceLoader、FileSystemResourceLoader、ClassRelativeResourceLoader 等。下面是一个简单的示例,演示 DefaultResourceLoader 的使用。
DefaultResourceLoaderExample
package c.jbd.spring.resources;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import java.io.IOException;
public class DefaultResourceLoaderExample {
public static void main(String[] args) throws IOException {
ResourceLoader resourceLoader = new DefaultResourceLoader();
Resource r = resourceLoader.getResource("sample.md");
ReaderUtil.readAndPrint(r.getInputStream());
}
}
ReaderUtil
package c.jbd.spring.resources;
import java.io.IOException;
import java.io.InputStream;
public class ReaderUtil {
public static void readAndPrint(InputStream stream) throws IOException {
int content = stream.read();
System.out.println("\n============ start ===========");
while (content != -1) {
System.out.print((char) content);
content = stream.read();
}
System.out.println("\n============ End ============");
stream.close();
}
}
============ start ===========
## This is a Sample Markdown file
============ End ============
请记住:所有应用程序上下文都实现了 ResourceLoader 接口。因此,您还可以使用应用程序上下文来获取资源实例。
ApplicationContext ctx = new ClassPathXmlApplicationContext();
Resource resource = ctx.getResource("conf/appContext.xml");
使用 ResourceLoaderAware 接口
在上一节中,我们学习了使用 ResourceLoader 接口。 Spring 还提供了一种通过实现 ResourceLoaderAware 接口在自定义组件中自动注入 ResourceLoader 的方法。
根据文档,ResourceLoaderAware 接口是一个特殊的回调接口,它标识期望提供 ResourceLoader 引用的组件。
JbdResourceLoader
package c.jbd.spring.resources.loader;
import c.jbd.spring.resources.ReaderUtil;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Component;
import java.io.IOException;
@Component("jbdResourceLoader")
public class JbdResourceLoader implements ResourceLoaderAware {
private ResourceLoader resourceLoader;
public void setResourceLoader(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
}
public void loadResource(String resourcePath) throws IOException {
Resource resource = resourceLoader.getResource(resourcePath);
ReaderUtil.readAndPrint(resource.getInputStream());
}
}
package c.jbd.spring.resources.loader;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import java.io.IOException;
public class ResourceLoaderDemo {
public static void main(String[] args) throws IOException {
ApplicationContext ctx = new AnnotationConfigApplicationContext(JbdResourceLoader.class);
JbdResourceLoader loader = (JbdResourceLoader) ctx.getBean("jbdResourceLoader");
loader.loadResource("classpath:sample.md");
System.out.println("*** Resource loader using classpath ***");
}
}
sample.md
## This is a Sample Markdown file
============ start ===========
## This is a Sample Markdown file
============ End ============
*** Resource loader using classpath ***
Resource字符串使用
您已经在上面的示例中看到,类路径资源作为 classpath:com/myapp/config.xml 传递,URL 资源作为 https://myserver/logo.png 传递。应该使用适当的前缀来指示其类型和位置。
Prefix | Example | Description |
---|---|---|
classpth: | classpath:resources/config.xml | The specified resource is loaded from the classpath |
file: | file:////data/config.yml | Loaded from the specified location on the local filesystem |
http:, ftp: | https://mysite/logo.png | Load the image from URL |
(empty) | /data/config.yml | Depends on the ApplicationContext implementation. |
注入资源作为依赖
您还可以将资源用作属性值。您可以使用@Value 注释来设置值。或者在您的 xml 配置中使用它,如下所示。
<bean id="myBean" class="...">
<property name="template" value="/resource/myTemplate.txt"/>
</bean>
@Component
public class AnyClass {
@Value("/resource/myTemplate.txt")
private String template;
...
}
资源路径中的通配符 (*)
应用程序上下文允许我们在资源路径中指定通配符模式 (*)。这些如下所示
/WEB-INF/*-context.xml
com/jbd/**/applicationContext.xml
file:C:/myapp/path/*-context.xml
classpath:com/jbd/**/applicationContext.xml
总结
本文为您提供了有关 Resource、ResourceLoader 和 ResourceLoaderAware 的信息。您已经了解了 Spring 中的资源以及 Spring 如何在内部处理它们。