1.1.1. Resource简介

在Spring内部实现机制,针对于资源文件(配置的xml文件)有一个统一的接口Resource。

1.1.1.1. 接口定义的方法

1.exists():判断资源文件是否存在。

2.isReadable():用于判断对应资源的内容是否可读。返回false肯定不可读,true也不一定可读。

3.isOpen():用于判断当前资源是否代表一个已打开的输入流,如果结果为true,则表示当前资源的输入流不可多次读取,而且在读取以后需要对它进行关闭,以防止内存泄露。该方法主要针对于InputStreamResource,实现类中只有它的返回结果为true,其他都为false。

4.getURL():返回当前资源对应的URL。如果当前资源不能解析为一个URL则会抛出异常。如ByteArrayResource就不能解析为一个URL。

5.getFile():返回当前资源对应的File。如果当前资源不能以绝对路径解析为一个File则会抛出异常。如ByteArrayResource就不能解析为一个File。

6.getInputStream():获取当前资源代表的输入流。除了InputStreamResource以外,其它Resource实现类每次调用getInputStream()方法都将返回一个全新的InputStream。

1.1.1.2. 接口继承关系

1.1.1.3. 接口实现类

主要常用的有如下:

ClassPathResource、FileSystemResource、UrlResource、ByteArrayResource、ServletContextResource和InputStreamResource。

1.1.1.4. ClassPathResource

主要应用于类路径下的资源文件使用classLoader类加载器进行读取使用

使用

ClassPathResource resource = new  ClassPathResource("springok/bean/beanFactory.xml");

System.out.println(resource.getFilename());

源码如下:

public ClassPathResource(String path, ClassLoader classLoader) {

Assert.notNull(path, "Path must not be null");

String pathToUse = StringUtils.cleanPath(path);

if (pathToUse.startsWith("/")) {

pathToUse = pathToUse.substring(1);

}

this.path = pathToUse;

this.classLoader = (classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader());

}

public InputStream getInputStream() throws IOException {

InputStream is;

if (this.clazz != null) {

is = this.clazz.getResourceAsStream(this.path);

}

else if (this.classLoader != null) {

is = this.classLoader.getResourceAsStream(this.path);

}

else {

is = ClassLoader.getSystemResourceAsStream(this.path);

}

if (is == null) {

throw new FileNotFoundException(getDescription() + " cannot be opened because it does not exist");

}

return is;

}

1.1.1.5. FileSystemResource

可用来获取文件系统里面的资源。

源码如下:

private final File file;

private final String path;

/**

* Create a new {@code FileSystemResource} from a {@link File} handle.

* <p>Note: When building relative resources via {@link #createRelative},

* the relative path will apply <i>at the same directory level</i>:

* e.g. new File("C:/dir1"), relative path "dir2" -> "C:/dir2"!

* If you prefer to have relative paths built underneath the given root

* directory, use the {@link #FileSystemResource(String) constructor with a file path}

* to append a trailing slash to the root path: "C:/dir1/", which

* indicates this directory as root for all relative paths.

* @param file a File handle

*/

public FileSystemResource(File file) {

Assert.notNull(file, "File must not be null");

this.file = file;

this.path = StringUtils.cleanPath(file.getPath());

}

1.1.1.6. UrlResource

代表URL对应的资源。

源码如下:

public InputStream getInputStream() throws IOException {

URLConnection con = this.url.openConnection();

ResourceUtils.useCachesIfNecessary(con);

try {

return con.getInputStream();

}

catch (IOException ex) {

// Close the HTTP connection (if applicable).

if (con instanceof HttpURLConnection) {

((HttpURLConnection) con).disconnect();

}

throw ex;

}

}

1.1.1.7. ByteArrayResource

针对于字节数组封装的资源,它的构建需要一个字节数组

源码如下:

private final byte[] byteArray;

private final String description;

/**

* Create a new ByteArrayResource.

* @param byteArray the byte array to wrap

*/

public ByteArrayResource(byte[] byteArray) {

this(byteArray, "resource loaded from byte array");

}

1.1.1.8. ServletContextResource

针对于ServletContext封装的资源,用于访问ServletContext环境下的资源。具体还是调用ServletContext 方法。

源码如下:

private final ServletContext servletContext;

private final String path;

public ServletContextResource(ServletContext servletContext, String path) {

// check ServletContext

Assert.notNull(servletContext, "Cannot resolve ServletContextResource without ServletContext");

this.servletContext = servletContext;

Assert.notNull(path, "Path is required");

String pathToUse = StringUtils.cleanPath(path);

if (!pathToUse.startsWith("/")) {

pathToUse = "/" + pathToUse;

}

this.path = pathToUse;

}

1.1.1.9. InputStreamResource

输入流封装的资源,它的构建需要一个输入流。

源码如下:

private final InputStream inputStream;

private final String description;

private boolean read = false;

public InputStreamResource(InputStream inputStream) {

this(inputStream, "resource loaded through InputStream");

}

1.1.2. 通过ResourceLoader获取资源

在Spring里面还定义有一个ResourceLoader接口,该接口中只定义了一个用于获取Resource的getResource(String location)方法。它的实现类有很多,这里我们先挑一个DefaultResourceLoader来讲。DefaultResourceLoader在获取Resource时采用的是这样的策略:首先判断指定的location是否含有“classpath:”前缀,如果有则把location去掉“classpath:”前缀返回对应的ClassPathResource;否则就把它当做一个URL来处理,封装成一个UrlResource进行返回;如果当成URL处理也失败的话就把location对应的资源当成是一个ClassPathResource进行返回。

源码如下:

public Resource getResource(String location) {

Assert.notNull(location, "Location must not be null");

//classpath:

if (location.startsWith(CLASSPATH_URL_PREFIX)) {

return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()), getClassLoader());

}

else {

try {

// Try to parse the location as a URL...

URL url = new URL(location);

return new UrlResource(url);

}

catch (MalformedURLException ex) {

// No URL -> resolve as resource path.

return getResourceByPath(location);

}

}

}

测试:

@Test

public void testResourceLoader() {

ResourceLoader loader = new DefaultResourceLoader();

Resource resource = loader.getResource("http://www.springok.com.");

System.out.println(resource instanceof UrlResource); //true

//注意这里前缀不能使用“classpath*:”,这样不能真正访问到对应的资源,exists()返回false

resource = loader.getResource("classpath:test.txt");

System.out.println(resource instanceof ClassPathResource); //true

resource = loader.getResource("test.txt");

System.out.println(resource instanceof ClassPathResource); //true

}

ApplicationContext接口也继承了ResourceLoader接口,所以它的所有实现类都实现了ResourceLoader接口,都可以用来获取Resource。

对于ClassPathXmlApplicationContext而言,它在获取Resource时继承的是它的父类DefaultResourceLoader的策略。

FileSystemXmlApplicationContext也继承了DefaultResourceLoader,但是它重写了DefaultResourceLoader的getResourceByPath(String path)方法。所以它在获取资源文件时首先也是判断指定的location是否包含“classpath:”前缀,如果包含,则把location中“classpath:”前缀后的资源从类路径下获取出来,当做一个ClassPathResource;否则,继续尝试把location封装成一个URL,返回对应的UrlResource;如果还是失败,则把location指定位置的资源当做一个FileSystemResource进行返回。

1.1.3. 在bean中获取Resource的方式

通过上面内容的介绍,我们知道,在bean中获取Resource主要有以下几种方式:

1.直接通过new各种类型的Resource来获取对应的Resource。

2.在bean里面获取到对应的ApplicationContext,再通过ApplicationContext的getResource(String path)方法获取对应的Resource。

3.直接创建DefaultResourceLoader的实例,再调用其getResource(String location)方法获取对应的Resource。

4.通过依赖注入的方式把Resource注入到bean中。示例如下:

使用比较简单如下:

public class ClassA {

//持有一个Resource属性

private Resource resource;

}

配置文件如下:

<bean id="" class="">

<property name="resource">

<value>classpath:applicationContext.xml</value>

</property>

</bean>

Spring Resource接口获取资源的更多相关文章

  1. 通过Spring Resource接口获取资源

    目录 1       Resource简介 2       通过ResourceLoader获取资源 3       在bean中获取Resource的方式 1       Resource简介 在S ...

  2. Bean利用Resource接口获取资源的几种方式

    Resources的类型 获取resource的方式(xml配置正常进行):

  3. [Spring] Resource 资源

    import ch.qos.logback.core.net.SyslogOutputStream; import org.springframework.core.io.ClassPathResou ...

  4. Spring源码分析——资源访问利器Resource之接口和抽象类分析

    从今天开始,一步步走上源码分析的路.刚开始肯定要从简单着手.我们先从Java发展史上最强大的框架——Spring...旗下的资源抽象接口Resource开始吧. 我看了好多分析Spring源码的,每每 ...

  5. 攻城狮在路上(贰) Spring(三)--- Spring 资源访问利器Resource接口

    Spring为了更好的满足各种底层资源的访问需求.设计了一个Resource接口,提供了更强的访问底层资源的能力.Spring框架使用Resource装载各种资源,包括配置文件资源.国际化属性文件资源 ...

  6. Spring源码分析——资源访问利器Resource之实现类分析

    今天来分析Spring的资源接口Resource的各个实现类.关于它的接口和抽象类,参见上一篇博文——Spring源码分析——资源访问利器Resource之接口和抽象类分析 一.文件系统资源 File ...

  7. spring资源访问接口和资源加载接口

    spring 资源访问接口 JDK提供的资源访问类,如java.net.URL.File等,不能很好地满足各种资源的访问需求,比如缺少从类路径或者Web容器的上下文中获取资源的操作类. 鉴于此,spr ...

  8. Resource接口,及资源

    Resource介绍 编码的时候,除了代码本身,我们还需要对外部的资源进行处理.例如:URL资源.URI资源.File资源.ClassPath相关资源.服务器相关资源(VFS等)等等. 而这些资源的处 ...

  9. 基础篇:JAVA资源之IO、字符编码、URL和Spring.Resource

    目录 1 JAVA.IO字节流 2 JAVA.IO字符流 3 乱码问题和字符流 4 字符集和字符编码的概念区分 5 URI概念的简单介绍 6 URL概念及与URL的区别 7 Spring.Resour ...

随机推荐

  1. [HAOI2008]硬币购物

    题目描述 硬币购物一共有4种硬币.面值分别为c1,c2,c3,c4.某人去商店买东西,去了tot次.每次带di枚ci硬币,买si的价值的东西.请问每次有多少种付款方法. 输入输出格式 输入格式: 第一 ...

  2. [ZJOI2011]看电影(MOVIE)

    题目描述 到了难得的假期,小白班上组织大家去看电影.但由于假期里看电影的人太多,很难做到让全班看上同一场电影,最后大家在一个偏僻的小胡同里找到了一家电影院.但这家电影院分配座位的方式很特殊,具体方式如 ...

  3. [Codeforces]848C - Goodbye Souvenir

    题目大意:n个数字,m次操作,支持修改一个数字和查询一个区间内每种数字最大出现位置减最小出现位置的和.(n,m<=100,000) 做法:把每个数字表示成二维平面上的点,第一维是在数组中的位置, ...

  4. ●SPOJ 7258 Lexicographical Substring Search

    题链: http://www.spoj.com/problems/SUBLEX/题解: 后缀自动机. 首先,因为相同的子串都被存在了自动机的同一个状态里面,所以这就很自然的避免了重复子串的问题. 然后 ...

  5. C++Primer学习——类

    我们在创建类的对象时,类不应该仅仅被声明,还应该被定义过,否则无法知道类占用了多少的内存 但是如果一个类的名字已经出现过就被认为是已经声明过了,所以允许包含自己的指针或者引用. 默认构造函数: 当类中 ...

  6. hdu 5398 动态树LCT

    GCD Tree Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Su ...

  7. [bzoj2648/2716]SJY摆棋子

    平面上有n个点,要求支持插入一个点和查询一个点的最近点距离 n,m<=500000 用kdtree实现,但是复杂度貌似没法保证.....(莫名加了替罪羊重建更慢了...) #include< ...

  8. mvn package 和 mvn install

    刚刚准备将maven项目中一个子项目打个包,使用了mvn package.心想这个很简单嘛,没料就报错了.报错咱不怕,看看错在哪就好了. 编译出错,找不到我定义的异常类中的配置.那应该是引用父模块出来 ...

  9. django之模板显示静态文件

    由于django的模板渲染机制,图片不能直接引用,否则不会显示. <img src="/static/img/logo.jpg"> 可以看出图片的大小轮廓,但并不显示内 ...

  10. 【转】动态规划DP

    [数据结构与算法] DP 动态规划 介绍 原创 2017年02月13日 00:42:51 最近在看算法导论. DP全称是dynamic programming,这里programming不是编程,是一 ...