静下心来的个人专栏
上一篇

在 Spring 中处理资源

广告
选中文字可对指定文章内容进行评论啦,→和←可快速切换按钮,绿色背景文字可以点击查看评论额。
大纲

在 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 接口。

  1. UrlResource
  2. ClassPathResource
  3. FileSystemResource
  4. ServletContextResource
  5. InputStreamResource
  6. 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 传递。应该使用适当的前缀来指示其类型和位置。

PrefixExampleDescription
classpth:classpath:resources/config.xmlThe specified resource is loaded from the classpath
file:file:////data/config.ymlLoaded from the specified location on the local filesystem
http:, ftp:https://mysite/logo.pngLoad the image from URL
(empty)/data/config.ymlDepends 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 如何在内部处理它们。

版权声明:著作权归作者所有。