Spring Resource接口获取资源

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>  

时间: 2024-09-19 09:54:47

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

【Spring】获取资源文件+从File+从InputStream对象获取正文数据

1.获取资源文件或者获取文本文件等,可以通过Spring的Resource的方式获取 2.仅有File对象即可获取正文数据 3.仅有InputStream即可获取正文数据   1 package com.sxd.test.test1; 2 3 import java.io.BufferedReader; 4 import java.io.File; 5 import java.io.FileReader; 6 import java.io.IOException; 7 import java.i

【spring Boot】spring boot获取资源文件的三种方式【两种情况下】

首先声明一点,springboot获取资源文件,需要看是 1>从spring boot默认的application.properties资源文件中获取 2>还是从自定义的资源文件中获取   带着这个想法去看下面几种方式 =============================================================================================== 1>从spring boot默认的application.properties资

开发app 手机如何从服务器获取资源

问题描述 开发app 手机如何从服务器获取资源 开发一款软件,但是手机运行拿不到服务器上的资源,用的是同一个局域网,怎么回事 解决方案 是报这个错么?android.os.NetworkOnMainThreadException 解决方案二: 拿不到,具体点.log 信息呢. 解决方案三: 服务器端给手机端接口,手机端通过网络进行访问 解决方案四: 引入HttpClient访问类 调用web地址,记住不能在主进程中调用,要开一个线程在线程中调用外部地址,否则报错,Android中主线程用来维护U

spring 注入问题 获取值为null

问题描述 spring 注入问题 获取值为null public interface UserService { void add(User user); } @Service public class UserServiceImpl implements UserService { @Resource private UserDao userDao; public void add(User user){ userDao.add(user); } } @Controller @Scope("p

【我的Android进阶之旅】Android使用getIdentifier()方法根据资源名来获取资源id

有时候我们想动态的根据一个资源名获得到对应的资源id,就可以使用getResources().getIdentifier()方法来获取该id.然后再使用该id进行相关的操作. 1.Demo示例 下面用一个小Demo来讲解如何使用getResources().getIdentifier()方法来获取该id. 例如,新建一个Android项目,项目结构部分截图如下所示: MainActivity代码如下: package com.oyp.demo; import android.os.Bundle;

Android中实现根据资源名获取资源ID_Android

接触过Android开发的同学们都知道在Android中访问程序资源基本都是通过资源ID来访问.这样开发起来很简单,并且可以不去考虑各种分辨率,语言等不同资源显式指定. 痛点 但是,有时候也会有一些问题,比如我们根据服务器端的值取图片,但是服务器端绝对不会返回给我们的是资源id,最多是一种和文件名相关联的值,操作资源少的时候,可以维护一个容器进行值与资源ID的映射,但是多的话,就需要另想办法了. 便捷的方法 在这种情况下,使用文件名来得到资源ID显得事半功倍. 通过调用Resources的get

Android使用getIdentifier()获取资源Id的方法_Android

本文实例讲述了Android使用getIdentifier()获取资源Id的方法.分享给大家供大家参考,具体如下: int i= getResources().getIdentifier("icon", "drawable", getPackageName()) ; if(i>0) {Log.i("aa","aa");} else {Log.i("vbv","aa");} 或者:

Android中实现根据资源名获取资源ID

接触过Android开发的同学们都知道在Android中访问程序资源基本都是通过资源ID来访问.这样开发起来很简单,并且可以不去考虑各种分辨率,语言等不同资源显式指定. 痛点 但是,有时候也会有一些问题,比如我们根据服务器端的值取图片,但是服务器端绝对不会返回给我们的是资源id,最多是一种和文件名相关联的值,操作资源少的时候,可以维护一个容器进行值与资源ID的映射,但是多的话,就需要另想办法了. 便捷的方法 在这种情况下,使用文件名来得到资源ID显得事半功倍. 通过调用Resources的get

Android使用getIdentifier()获取资源Id的方法

本文实例讲述了Android使用getIdentifier()获取资源Id的方法.分享给大家供大家参考,具体如下: int i= getResources().getIdentifier("icon", "drawable", getPackageName()) ; if(i>0) {Log.i("aa","aa");} else {Log.i("vbv","aa");} 或者: