spring之资源操作:Resources

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
Serverless 应用引擎免费试用套餐包,4320000 CU,有效期3个月
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: 【1月更文挑战第17天】一、Spring Resources概述二、Resource接口三、Resource的实现类1、UrlResource访问网络资源2、ClassPathResource 访问类路径下资源3、FileSystemResource 访问文件系统资源4、ServletContextResource5、InputStreamResource6、ByteArrayResource四、Resource类图五、ResourceLoader 接口1、ResourceLoader 概述2、使用演示3、ResourceLoader 总结六、ResourceLo

文章目录

前言

一、Spring Resources概述

二、Resource接口

三、Resource的实现类

1、UrlResource访问网络资源

2、ClassPathResource 访问类路径下资源

3、FileSystemResource 访问文件系统资源

4、ServletContextResource

5、InputStreamResource

6、ByteArrayResource

四、Resource类图

五、ResourceLoader 接口

1、ResourceLoader 概述

2、使用演示

3、ResourceLoader 总结

六、ResourceLoaderAware 接口

七、使用Resource 作为属性

八、应用程序上下文和资源路径

1、概述

2、ApplicationContext实现类指定访问策略

3、使用前缀指定访问策略

总结


前言

一、Spring Resources概述

二、Resource接口

三、Resource的实现类

1、UrlResource访问网络资源

2、ClassPathResource 访问类路径下资源

3、FileSystemResource 访问文件系统资源

4、ServletContextResource

5、InputStreamResource

6、ByteArrayResource

四、Resource类图

五、ResourceLoader 接口

1、ResourceLoader 概述

2、使用演示

3、ResourceLoader 总结

六、ResourceLoaderAware 接口

七、使用Resource 作为属性

八、应用程序上下文和资源路径

1、概述

2、ApplicationContext实现类指定访问策略

3、使用前缀指定访问策略


一、Spring Resources概述

Java的标准java.net.URL类和各种URL前缀的标准处理程序无法满足所有对low-level资源的访问,比如:没有标准化的 URL 实现可用于访问需要从类路径或相对于 ServletContext 获取的资源。并且缺少某些Spring所需要的功能,例如检测某资源是否存在等。而Spring的Resource声明了访问low-level资源的能力。

二、Resource接口

Spring 的 Resource 接口位于 org.springframework.core.io 中。 旨在成为一个更强大的接口,用于抽象对低级资源的访问。以下显示了Resource接口定义的方法

publicinterfaceResourceextendsInputStreamSource {
booleanexists();
booleanisReadable();
booleanisOpen();
booleanisFile();
URLgetURL() throwsIOException;
URIgetURI() throwsIOException;
FilegetFile() throwsIOException;
ReadableByteChannelreadableChannel() throwsIOException;
longcontentLength() throwsIOException;
longlastModified() throwsIOException;
ResourcecreateRelative(StringrelativePath) throwsIOException;
StringgetFilename();
StringgetDescription();
}

Resource接口继承了InputStreamSource接口,提供了很多InputStreamSource所没有的方法。InputStreamSource接口,只有一个方法:

publicinterfaceInputStreamSource {
InputStreamgetInputStream() throwsIOException;
}

其中一些重要的方法:

getInputStream(): 找到并打开资源,返回一个InputStream以从资源中读取。预计每次调用都会返回一个新的InputStream(),调用者有责任关闭每个流

exists(): 返回一个布尔值,表明某个资源是否以物理形式存在

isOpen: 返回一个布尔值,指示此资源是否具有开放流的句柄。如果为true,InputStream就不能够多次读取,只能够读取一次并且及时关闭以避免内存泄漏。对于所有常规资源实现,返回false,但是InputStreamResource除外。

getDescription(): 返回资源的描述,用来输出错误的日志。这通常是完全限定的文件名或资源的实际URL。

其他方法:

isReadable(): 表明资源的目录读取是否通过getInputStream()进行读取。

isFile(): 表明这个资源是否代表了一个文件系统的文件。

getURL(): 返回一个URL句柄,如果资源不能够被解析为URL,将抛出IOException

getURI(): 返回一个资源的URI句柄

getFile(): 返回某个文件,如果资源不能够被解析称为绝对路径,将会抛出FileNotFoundException

lastModified(): 资源最后一次修改的时间戳

createRelative(): 创建此资源的相关资源

getFilename(): 资源的文件名是什么 例如:最后一部分的文件名 myfile.txt

三、Resource的实现类

Resource 接口是 Spring 资源访问策略的抽象,它本身并不提供任何资源访问实现,具体的资源访问由该接口的实现类完成——每个实现类代表一种资源访问策略。Resource一般包括这些实现类:UrlResource、ClassPathResource、FileSystemResource、ServletContextResource、InputStreamResource、ByteArrayResource

1、UrlResource访问网络资源

Resource的一个实现类,用来访问网络资源,它支持URL的绝对路径。

http:------该前缀用于访问基于HTTP协议的网络资源。

ftp:------该前缀用于访问基于FTP协议的网络资源

file: ------该前缀用于从文件系统中读取资源

实验:访问基于HTTP协议的网络资源

创建一个maven子模块spring6-resources,配置Spring依赖(参考前面)

packagecom.atguigu.spring6.resources;
importorg.springframework.core.io.UrlResource;
publicclassUrlResourceDemo {
publicstaticvoidloadAndReadUrlResource(Stringpath){
// 创建一个 Resource 对象UrlResourceurl=null;
try {
url=newUrlResource(path);
// 获取资源名System.out.println(url.getFilename());
System.out.println(url.getURI());
// 获取资源描述System.out.println(url.getDescription());
//获取资源内容System.out.println(url.getInputStream().read());
        } catch (Exceptione) {
thrownewRuntimeException(e);
        }
    }
publicstaticvoidmain(String[] args) {
//访问网络资源loadAndReadUrlResource("http://www.baidu.com");
    }
}

实验二:在项目根路径下创建文件,从文件系统中读取资源

方法不变,修改调用传递路径

publicstaticvoidmain(String[] args) {
//1 访问网络资源//loadAndReadUrlResource("http://www.atguigu.com");//2 访问文件系统资源loadAndReadUrlResource("file:atguigu.txt");
}

2、ClassPathResource 访问类路径下资源

ClassPathResource 用来访问类加载路径下的资源,相对于其他的 Resource 实现类,其主要优势是方便访问类加载路径里的资源,尤其对于 Web 应用,ClassPathResource 可自动搜索位于 classes 下的资源文件,无须使用绝对路径访问。

实验:在类路径下创建文件atguigu.txt,使用ClassPathResource 访问

packagecom.atguigu.spring6.resources;
importorg.springframework.core.io.ClassPathResource;
importjava.io.InputStream;
publicclassClassPathResourceDemo {
publicstaticvoidloadAndReadUrlResource(Stringpath) throwsException{
// 创建一个 Resource 对象ClassPathResourceresource=newClassPathResource(path);
// 获取文件名System.out.println("resource.getFileName = "+resource.getFilename());
// 获取文件描述System.out.println("resource.getDescription = "+resource.getDescription());
//获取文件内容InputStreamin=resource.getInputStream();
byte[] b=newbyte[1024];
while(in.read(b)!=-1) {
System.out.println(newString(b));
        }
    }
publicstaticvoidmain(String[] args) throwsException {
loadAndReadUrlResource("atguigu.txt");
    }
}

ClassPathResource实例可使用ClassPathResource构造器显式地创建,但更多的时候它都是隐式地创建的。当执行Spring的某个方法时,该方法接受一个代表资源路径的字符串参数,当Spring识别该字符串参数中包含classpath:前缀后,系统会自动创建ClassPathResource对象。

3、FileSystemResource 访问文件系统资源

Spring 提供的 FileSystemResource 类用于访问文件系统资源,使用 FileSystemResource 来访问文件系统资源并没有太大的优势,因为 Java 提供的 File 类也可用于访问文件系统资源。

实验:使用FileSystemResource 访问文件系统资源

packagecom.atguigu.spring6.resources;
importorg.springframework.core.io.FileSystemResource;
importjava.io.InputStream;
publicclassFileSystemResourceDemo {
publicstaticvoidloadAndReadUrlResource(Stringpath) throwsException{
//相对路径FileSystemResourceresource=newFileSystemResource("atguigu.txt");
//绝对路径//FileSystemResource resource = new FileSystemResource("C:\\atguigu.txt");// 获取文件名System.out.println("resource.getFileName = "+resource.getFilename());
// 获取文件描述System.out.println("resource.getDescription = "+resource.getDescription());
//获取文件内容InputStreamin=resource.getInputStream();
byte[] b=newbyte[1024];
while(in.read(b)!=-1) {
System.out.println(newString(b));
        }
    }
publicstaticvoidmain(String[] args) throwsException {
loadAndReadUrlResource("atguigu.txt");
    }
}

FileSystemResource实例可使用FileSystemResource构造器显示地创建,但更多的时候它都是隐式创建。执行Spring的某个方法时,该方法接受一个代表资源路径的字符串参数,当Spring识别该字符串参数中包含file:前缀后,系统将会自动创建FileSystemResource对象。

4、ServletContextResource

这是ServletContext资源的Resource实现,它解释相关Web应用程序根目录中的相对路径。它始终支持流(stream)访问和URL访问,但只有在扩展Web应用程序存档且资源实际位于文件系统上时才允许java.io.File访问。无论它是在文件系统上扩展还是直接从JAR或其他地方(如数据库)访问,实际上都依赖于Servlet容器。

5、InputStreamResource

InputStreamResource 是给定的输入流(InputStream)的Resource实现。它的使用场景在没有特定的资源实现的时候使用(感觉和@Component 的适用场景很相似)。与其他Resource实现相比,这是已打开资源的描述符。 因此,它的isOpen()方法返回true。如果需要将资源描述符保留在某处或者需要多次读取流,请不要使用它。

6、ByteArrayResource

字节数组的Resource实现类。通过给定的数组创建了一个ByteArrayInputStream。它对于从任何给定的字节数组加载内容非常有用,而无需求助于单次使用的InputStreamResource。

四、Resource类图

上述Resource实现类与Resource顶级接口之间的关系可以用下面的UML关系模型来表示

五、ResourceLoader 接口

1、ResourceLoader 概述

Spring 提供如下两个标志性接口:

(1)ResourceLoader : 该接口实现类的实例可以获得一个Resource实例。

(2) ResourceLoaderAware : 该接口实现类的实例将获得一个ResourceLoader的引用。

在ResourceLoader接口里有如下方法:

(1)Resource getResource(String location) : 该接口仅有这个方法,用于返回一个Resource实例。ApplicationContext实现类都实现ResourceLoader接口,因此ApplicationContext可直接获取Resource实例。

2、使用演示

实验一:ClassPathXmlApplicationContext获取Resource实例

packagecom.atguigu.spring6.resouceloader;
importorg.springframework.context.ApplicationContext;
importorg.springframework.context.support.ClassPathXmlApplicationContext;
importorg.springframework.core.io.Resource;
publicclassDemo1 {
publicstaticvoidmain(String[] args) {
ApplicationContextctx=newClassPathXmlApplicationContext();
//        通过ApplicationContext访问资源//        ApplicationContext实例获取Resource实例时,//        默认采用与ApplicationContext相同的资源访问策略Resourceres=ctx.getResource("atguigu.txt");
System.out.println(res.getFilename());
    }
}

实验二:FileSystemApplicationContext获取Resource实例

packagecom.atguigu.spring6.resouceloader;
importorg.springframework.context.ApplicationContext;
importorg.springframework.context.support.FileSystemXmlApplicationContext;
importorg.springframework.core.io.Resource;
publicclassDemo2 {
publicstaticvoidmain(String[] args) {
ApplicationContextctx=newFileSystemXmlApplicationContext();
Resourceres=ctx.getResource("atguigu.txt");
System.out.println(res.getFilename());
    }
}

3、ResourceLoader 总结

Spring将采用和ApplicationContext相同的策略来访问资源。也就是说,如果ApplicationContext是FileSystemXmlApplicationContext,res就是FileSystemResource实例;如果ApplicationContext是ClassPathXmlApplicationContext,res就是ClassPathResource实例

当Spring应用需要进行资源访问时,实际上并不需要直接使用Resource实现类,而是调用ResourceLoader实例的getResource()方法来获得资源,ReosurceLoader将会负责选择Reosurce实现类,也就是确定具体的资源访问策略,从而将应用程序和具体的资源访问策略分离开来

另外,使用ApplicationContext访问资源时,可通过不同前缀指定强制使用指定的ClassPathResource、FileSystemResource等实现类

Resourceres=ctx.getResource("calsspath:bean.xml");
Resrouceres=ctx.getResource("file:bean.xml");
Resourceres=ctx.getResource("http://localhost:8080/beans.xml");

六、ResourceLoaderAware 接口

ResourceLoaderAware接口实现类的实例将获得一个ResourceLoader的引用,ResourceLoaderAware接口也提供了一个setResourceLoader()方法,该方法将由Spring容器负责调用,Spring容器会将一个ResourceLoader对象作为该方法的参数传入。

如果把实现ResourceLoaderAware接口的Bean类部署在Spring容器中,Spring容器会将自身当成ResourceLoader作为setResourceLoader()方法的参数传入。由于ApplicationContext的实现类都实现了ResourceLoader接口,Spring容器自身完全可作为ResorceLoader使用。

实验:演示ResourceLoaderAware使用

第一步 创建类,实现ResourceLoaderAware接口

packagecom.atguigu.spring6.resouceloader;
importorg.springframework.context.ResourceLoaderAware;
importorg.springframework.core.io.ResourceLoader;
publicclassTestBeanimplementsResourceLoaderAware {
privateResourceLoaderresourceLoader;
//实现ResourceLoaderAware接口必须实现的方法//如果把该Bean部署在Spring容器中,该方法将会有Spring容器负责调用。//SPring容器调用该方法时,Spring会将自身作为参数传给该方法。publicvoidsetResourceLoader(ResourceLoaderresourceLoader) {
this.resourceLoader=resourceLoader;
    }
//返回ResourceLoader对象的应用publicResourceLoadergetResourceLoader(){
returnthis.resourceLoader;
    }
}

第二步 创建bean.xml文件,配置TestBean

<?xmlversion="1.0" encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><beanid="testBean"class="com.atguigu.spring6.resouceloader.TestBean"></bean></beans>

第三步 测试

packagecom.atguigu.spring6.resouceloader;
importorg.springframework.context.ApplicationContext;
importorg.springframework.context.support.ClassPathXmlApplicationContext;
importorg.springframework.core.io.Resource;
importorg.springframework.core.io.ResourceLoader;
publicclassDemo3 {
publicstaticvoidmain(String[] args) {
//Spring容器会将一个ResourceLoader对象作为该方法的参数传入ApplicationContextctx=newClassPathXmlApplicationContext("bean.xml");
TestBeantestBean=ctx.getBean("testBean",TestBean.class);
//获取ResourceLoader对象ResourceLoaderresourceLoader=testBean.getResourceLoader();
System.out.println("Spring容器将自身注入到ResourceLoaderAware Bean 中 ? :"+ (resourceLoader==ctx));
//加载其他资源Resourceresource=resourceLoader.getResource("atguigu.txt");
System.out.println(resource.getFilename());
System.out.println(resource.getDescription());
    }
}

七、使用Resource 作为属性

前面介绍了 Spring 提供的资源访问策略,但这些依赖访问策略要么需要使用 Resource 实现类,要么需要使用 ApplicationContext 来获取资源。实际上,当应用程序中的 Bean 实例需要访问资源时,Spring 有更好的解决方法:直接利用依赖注入。从这个意义上来看,Spring 框架不仅充分利用了策略模式来简化资源访问,而且还将策略模式和 IoC 进行充分地结合,最大程度地简化了 Spring 资源访问。

归纳起来,如果 Bean 实例需要访问资源,有如下两种解决方案:

  • 代码中获取 Resource 实例。
  • 使用依赖注入。

对于第一种方式,当程序获取 Resource 实例时,总需要提供 Resource 所在的位置,不管通过 FileSystemResource 创建实例,还是通过 ClassPathResource 创建实例,或者通过 ApplicationContext 的 getResource() 方法获取实例,都需要提供资源位置。这意味着:资源所在的物理位置将被耦合到代码中,如果资源位置发生改变,则必须改写程序。因此,通常建议采用第二种方法,让 Spring 为 Bean 实例依赖注入资源。

实验:让Spring为Bean实例依赖注入资源

第一步 创建依赖注入类,定义属性和方法

packagecom.atguigu.spring6.resouceloader;
importorg.springframework.core.io.Resource;
publicclassResourceBean {
privateResourceres;
publicvoidsetRes(Resourceres) {
this.res=res;
    }
publicResourcegetRes() {
returnres;
    }
publicvoidparse(){
System.out.println(res.getFilename());
System.out.println(res.getDescription());
    }
}

第二步 创建spring配置文件,配置依赖注入

<?xmlversion="1.0" encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><beanid="resourceBean"class="com.atguigu.spring6.resouceloader.ResourceBean"><!-- 可以使用file:、http:、ftp:等前缀强制Spring采用对应的资源访问策略 --><!-- 如果不采用任何前缀,则Spring将采用与该ApplicationContext相同的资源访问策略来访问资源 --><propertyname="res"value="classpath:atguigu.txt"/></bean></beans>

第三步 测试

packagecom.atguigu.spring6.resouceloader;
importorg.springframework.context.ApplicationContext;
importorg.springframework.context.support.ClassPathXmlApplicationContext;
publicclassDemo4 {
publicstaticvoidmain(String[] args) {
ApplicationContextctx=newClassPathXmlApplicationContext("bean.xml");
ResourceBeanresourceBean=ctx.getBean("resourceBean",ResourceBean.class);
resourceBean.parse();
    }
}

八、应用程序上下文和资源路径

1、概述

不管以怎样的方式创建ApplicationContext实例,都需要为ApplicationContext指定配置文件,Spring允许使用一份或多分XML配置文件。当程序创建ApplicationContext实例时,通常也是以Resource的方式来访问配置文件的,所以ApplicationContext完全支持ClassPathResource、FileSystemResource、ServletContextResource等资源访问方式。

ApplicationContext确定资源访问策略通常有两种方法:

(1)使用ApplicationContext实现类指定访问策略。

(2)使用前缀指定访问策略。

2、ApplicationContext实现类指定访问策略

创建ApplicationContext对象时,通常可以使用如下实现类:

(1) ClassPathXMLApplicationContext : 对应使用ClassPathResource进行资源访问。

(2)FileSystemXmlApplicationContext : 对应使用FileSystemResource进行资源访问。

(3)XmlWebApplicationContext : 对应使用ServletContextResource进行资源访问。

当使用ApplicationContext的不同实现类时,就意味着Spring使用响应的资源访问策略。

效果前面已经演示

3、使用前缀指定访问策略

实验一:classpath前缀使用

packagecom.atguigu.spring6.context;
importorg.springframework.context.ApplicationContext;
importorg.springframework.context.support.FileSystemXmlApplicationContext;
importorg.springframework.core.io.Resource;
publicclassDemo1 {
publicstaticvoidmain(String[] args) {
/** 通过搜索文件系统路径下的xml文件创建ApplicationContext,* 但通过指定classpath:前缀强制搜索类加载路径* classpath:bean.xml* */ApplicationContextctx=newClassPathXmlApplicationContext("classpath:bean.xml");
System.out.println(ctx);
Resourceresource=ctx.getResource("atguigu.txt");
System.out.println(resource.getFilename());
System.out.println(resource.getDescription());
    }
}

实验二:classpath通配符使用

classpath * :前缀提供了加载多个XML配置文件的能力,当使用classpath*:前缀来指定XML配置文件时,系统将搜索类加载路径,找到所有与文件名匹配的文件,分别加载文件中的配置定义,最后合并成一个ApplicationContext。

ApplicationContextctx=newClassPathXmlApplicationContext("classpath*:bean.xml");
System.out.println(ctx);

当使用classpath * :前缀时,Spring将会搜索类加载路径下所有满足该规则的配置文件。

如果不是采用classpath * :前缀,而是改为使用classpath:前缀,Spring则只加载第一个符合条件的XML文件

注意 :

classpath * : 前缀仅对ApplicationContext有效。实际情况是,创建ApplicationContext时,分别访问多个配置文件(通过ClassLoader的getResource方法实现)。因此,classpath * :前缀不可用于Resource。

使用三:通配符其他使用

一次性加载多个配置文件的方式:指定配置文件时使用通配符

ApplicationContextctx=newClassPathXmlApplicationContext("classpath:bean*.xml");

Spring允许将classpath*:前缀和通配符结合使用:

ApplicationContextctx=newClassPathXmlApplicationContext("classpath*:bean*.xml");

总结

以上就是spring之资源操作:Resources的相关知识点,希望对你有所帮助。

积跬步以至千里,积怠惰以至深渊。时代在这跟着你一起努力哦!

相关文章
|
6月前
|
XML Java 数据格式
spring Resources
spring Resources
65 0
|
3月前
|
前端开发 JavaScript Java
Spring Boot应用中的资源分离与高效打包实践
通过实施资源分离和高效打包策略,不仅可以提升Spring Boot应用的开发和部署效率,还能显著提高用户体验。在实际项目中,根据项目的实际情况和团队的技术栈选择合适的工具和方案是关键。希望本文能为读者在Spring Boot项目中实现资源分离和高效打包提供一些有价值的参考。
|
4月前
|
前端开发 JavaScript Java
使用Spring Boot实现跨域资源共享(CORS)
使用Spring Boot实现跨域资源共享(CORS)
|
4月前
|
前端开发 JavaScript Java
使用Spring Boot实现跨域资源共享(CORS)
使用Spring Boot实现跨域资源共享(CORS)
|
4月前
|
存储 Java 数据库连接
Spring6(五):Resources、i18n、Validation(3)
Spring6(五):Resources、i18n、Validation(3)
18 0
|
4月前
|
XML Java 数据格式
Spring6(五):Resources、i18n、Validation(2)
Spring6(五):Resources、i18n、Validation(2)
46 0
|
4月前
|
Java 数据库 uml
Spring6(五):Resources、i18n、Validation(1)
Spring6(五):Resources、i18n、Validation(1)
28 0
|
6月前
|
Java 开发者 Spring
Spring Boot中的资源文件属性配置
【4月更文挑战第28天】在Spring Boot应用程序中,配置文件是管理应用程序行为的重要组成部分。资源文件属性配置允许开发者在不重新编译代码的情况下,对应用程序进行灵活地配置和调整。本篇博客将介绍Spring Boot中资源文件属性配置的基本概念,并通过实际示例展示如何利用这一功能。
64 1
|
6月前
|
前端开发 Java Spring
Spring5源码(14)-Spring资源文件读取
Spring5源码(14)-Spring资源文件读取
45 1
|
6月前
|
存储 Java Maven
SpringCloud Oauth2.0 实现资源验证
SpringCloud Oauth2.0 实现资源验证
70 0