资源 Resource

Resource接口他是继承InputStreamSource

public interface InputStreamSource {

    InputStream getInputStream() throws IOException;

}

Spring的 Resource 接口是为了提供更强的访问底层资源能力的抽象。

/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springframework.core.io;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URL;

/**
* Interface for a resource descriptor that abstracts from the actual
* type of underlying resource, such as a file or class path resource.
*
* <p>An InputStream can be opened for every resource if it exists in
* physical form, but a URL or File handle can just be returned for
* certain resources. The actual behavior is implementation-specific.
*
* @author Juergen Hoeller
* @since 28.12.2003
* @see #getInputStream()
* @see #getURL()
* @see #getURI()
* @see #getFile()
* @see FileSystemResource
* @see ClassPathResource
* @see UrlResource
* @see ByteArrayResource
* @see InputStreamResource
* @see org.springframework.web.context.support.ServletContextResource
*/
public interface Resource extends InputStreamSource {

/**
* Return whether this resource actually exists in physical form.
* <p>This method performs a definitive existence check, whereas the
* existence of a <code>Resource</code> handle only guarantees a
* valid descriptor handle.
*/
boolean exists();

/**
* Return whether the contents of this resource can be read,
* e.g. via {@link #getInputStream()} or {@link #getFile()}.
* <p>Will be <code>true</code> for typical resource descriptors;
* note that actual content reading may still fail when attempted.
* However, a value of <code>false</code> is a definitive indication
* that the resource content cannot be read.
*/
boolean isReadable();

/**
* Return whether this resource represents a handle with an open
* stream. If true, the InputStream cannot be read multiple times,
* and must be read and closed to avoid resource leaks.
* <p>Will be <code>false</code> for typical resource descriptors.
*/
boolean isOpen();

/**
* Return a URL handle for this resource.
* @throws IOException if the resource cannot be resolved as URL,
* i.e. if the resource is not available as descriptor
*/
URL getURL() throws IOException;

/**
* Return a URI handle for this resource.
* @throws IOException if the resource cannot be resolved as URI,
* i.e. if the resource is not available as descriptor
*/
URI getURI() throws IOException;

/**
* Return a File handle for this resource.
* @throws IOException if the resource cannot be resolved as absolute
* file path, i.e. if the resource is not available in a file system
*/
File getFile() throws IOException;

/**
* Determine the content length for this resource.
* @throws IOException if the resource cannot be resolved
* (in the file system or as some other known physical resource type)
*/
long contentLength() throws IOException;

/**
* Determine the last-modified timestamp for this resource.
* @throws IOException if the resource cannot be resolved
* (in the file system or as some other known physical resource type)
*/
long lastModified() throws IOException;

/**
* Create a resource relative to this resource.
* @param relativePath the relative path (relative to this resource)
* @return the resource handle for the relative resource
* @throws IOException if the relative resource cannot be determined
*/
Resource createRelative(String relativePath) throws IOException;

/**
* Return a filename for this resource, i.e. typically the last
* part of the path: for example, "myfile.txt".
*/
String getFilename();

/**
* Return a description for this resource,
* to be used for error output when working with the resource.
* <p>Implementations are also encouraged to return this value
* from their <code>toString</code> method.
* @see java.lang.Object#toString()
*/
String getDescription();

}

Resource 接口一些比较重要的方法如下:

getInputStream(): 定位并打开资源,返回读取此资源的一个 InputStream。每次调用预期会返回一个新的 InputStream,由调用者负责关闭这个流。

exists(): 返回标识这个资源在物理上是否的确存在的 boolean 值。

isOpen(): 返回标识这个资源是否有已打开流的处理类的 boolean 值。如果为 true,则此InputStream 就不能被多次读取, 而且只能被读取一次然后关闭以避免资源泄漏。除了 InputStreamResource,常见的resource实现都会返回 false。

getDescription(): 返回资源的描述,一般在与此资源相关的错误输出时使用。此描述通常是完整的文件名或实际的URL地址。

其它方法让你获得表示该资源的实际的 URL 或 File 对象(如果隐含的实现支持该方法并保持一致的话)。

Spring自身处理资源请求的多种方法声明中将Resource 抽象作为参数而广泛地使用。 Spring APIs中的一些其它方法(比如许多ApplicationContext的实现构造函数),使用普通格式的 String 来创建与context相符的Resource,也可以使用特殊的路径String前缀来让调用者指定创建和使用特定的 Resource 实现。

Resource不仅被Spring自身大量地使用,它也非常适合在你自己的代码中独立作为辅助类使用。 用户代码甚至可以在不用关心Spring其它部分的情况下访问资源。这样的确会造成代码与Spring之间的耦合,但也仅仅是与很少量的辅助类耦合。这些类可以作为比 URL 更有效的替代,而且与为这个目的而使用其它类库基本相似。

需要注意的是 Resource 抽象并没有改变功能:它尽量使用封装。 比如 UrlResource 封装了URL,然后使用被封装的 URL 来工作。

Spring提供了很多 Resource 的实现:

UrlResource

UrlResource 封装了java.net.URL,它能够被用来访问任何通过URL可以获得的对象,例如:文件、HTTP对象、FTP对象等。所有的URL都有个标准的 String表示,这些标准前缀可以标识不同的URL类型,包括file:访问文件系统路径,http: 通过HTTP协议访问的资源,ftp: 通过FTP访问的资源等等。

UrlResource 对象可以在Java代码中显式地使用 UrlResource 构造函数来创建。但更多的是通过调用带表示路径的 String 参数的API函数隐式地创建。在后一种情况下,JavaBeans的 PropertyEditor 会最终决定哪种类型的 Resource 被创建。如果这个字符串包含一些众所周知的前缀,比如 classpath:,它就会创建一个对应的已串行化的 Resource。 然而,如果不能分辨出这个前缀,就会假定它是个标准的URL字符串,然后创建UrlResource。

ClassPathResource

这个类标识从classpath获得的资源。它会使用线程context的类加载器(class loader)、给定的类加载器或者用来载入资源的给定类。

如果类路径上的资源存在于文件系统里,这个 Resource 的实现会提供类似于java.io.File的功能。而如果资源是存在于还未解开(被servlet引擎或其它的环境解开)的jar包中,这些 Resource 实现会提供类似于java.net.URL 的功能。

ClassPathResource对象可以在Java代码中显式地使用ClassPathResource 构造函数来创建。但更多的是通过调用带表示路径的String参数的API函数隐式地创建。在后一种情况下,JavaBeans的 PropertyEditor 会分辨字符串中 classpath: 前缀,然后相应创建 ClassPathResource。

FileSystemResource

这是为处理 java.io.File 而准备的Resource实现。它既可以作为File提供,也可以作为URL。

ServletContextResource

这是为 ServletContext 资源提供的 Resource 实现,它负责解析相关web应用根目录中的相对路径。

它始终支持以流和URL的方式访问。 但是只有当web应用包被解开并且资源在文件系统的物理路径上时,才允许以 java.io.File 方式访问。是否解开并且在文件系统中访问,还是直接从JAR包访问或以其它方式访问如DB(这是可以想象的),仅取决于Servlet容器。

InputStreamResource

这是为给定的 InputStream 而准备的 Resource 实现。它只有在没有其它合适的 Resource 实现时才使用。而且,只要有可能就尽量使用 ByteArrayResource 或者其它基于文件的Resource 实现。

与其它 Resource 实现不同的是,这是个 已经 打开资源的描述符-因此 isOpen() 函数返回 true。 如果你需要在其它位置保持这个资源的描述符或者多次读取一个流,请不要使用它。

ByteArrayResource

这是为给定的byte数组准备的 Resource 实现。 它会为给定的byte数组构造一个 ByteArrayInputStream。

它在从任何给定的byte数组读取内容时很有用,因为不用转换成单一作用的 InputStreamResource。

ResourceLoader接口

ResourceLoader 接口由能返回(或者载入)Resource 实例的对象来实现。

public interface ResourceLoader {
    Resource getResource(String location);
}

所有的application context都实现了 ResourceLoader 接口, 因此它们可以用来获取Resource 实例。

当你调用特定application context的 getResource() 方法, 而且资源路径并没有特定的前缀时,你将获得与该application context相应的 Resource 类型。例如:假定下面的代码片断是基于ClassPathXmlApplicationContext 实例上执行的:

Resource template = ctx.getResource("some/resource/path/myTemplate.txt");
这将返回ClassPathResource;如果是基于FileSystemXmlApplicationContext 实例上执行的,那你将获得FileSystemResource。而对于 WebApplicationContext 你将获得ServletContextResource,依此类推。

这样你可以在特定的application context中用流行的方法载入资源。

另一方面,无论什么类型的application context, 你可以通过使用特定的前缀 classpath: 强制使用ClassPathResource。

Resource template = ctx.getResource("classpath:some/resource/path/myTemplate.txt");
同样的,你可以用任何标准的 java.net.URL 前缀,强制使用 UrlResource :

Resource template = ctx.getResource("file:/some/resource/path/myTemplate.txt");
Resource template = ctx.getResource("http://myhost.com/resource/path/myTemplate.txt");
下面的表格概述了 String 到 Resource 的转换规则:

Table 4.1. Resource strings

前缀 例子 说明
classpath:

classpath:com/myapp/config.xml

从classpath中加载。

file:

file:/data/config.xml

作为 URL 从文件系统中加载。[a]

http:

http://myserver/logo.png

作为 URL 加载。

(none)

/data/config.xml

根据 ApplicationContext 进行判断。

猜你喜欢

转载自liyixing1.iteye.com/blog/1038144
今日推荐