资源管理
资源管理是Spring的一个核心的基础功能,不过在说Spring的资源管理之前,先来简单说一下Java中的资源管理。
Java资源管理
Java中的资源管理主要是通过java.net.URL
来实现的,通过URL的openConnection
方法可以对资源打开一个连接,通过这个连接读取资源的内容。
资源不仅仅指的是网络资源,还可以是本地文件、一个jar包等等。
1、来个Demo
举个例子,比如你想到访问www.baidu.com
这个百度首页网络资源,那么此时就可以这么写
public class JavaResourceDemo {
public static void main(String[] args) throws IOException {
//构建URL 指定资源的协议为http协议
URL url = new URL("http://www.baidu.com");
//打开资源连接
URLConnection urlConnection = url.openConnection();
//获取资源输入流
InputStream inputStream = urlConnection.getInputStream();
//通过hutool工具类读取流中数据
String content = IoUtil.read(new InputStreamReader(inputStream));
System.out.println(content);
}
}
解释一下上面代码的意思:
-
首先构建一个URL,指定资源的访问协议为http协议
-
通过URL打开一个资源访问连接,然后获取一个输入流,读取内容
运行结果
成功读取到百度首页的数据。
当然,也可以通过URL访问本地文件资源,在创建URL的时候只需要指定协议类型为file://
和文件的路径就行了
URL url = new URL("file://" + "文件的路径");
这种方式这里我就不演示了。
其实这种方式实际上最终也是通过FileInputStream
来读取文件数据的,不信你可以自己debug试试。
2、原理
每种协议的URL资源都需要一个对应的一个URLStreamHandler来处理。
URLStreamHandler
比如说,http://
协议有对应的URLStreamHandler的实现,file://
协议的有对应的URLStreamHandler的实现。
Java除了支持http://
和file://
协议之外,还支持其它的协议,如下图所示:
对于的URLStreamHandler如下图所示
当在构建URL的时候,会去解析资源的访问协议,根据访问协议找到对应的URLStreamHandler的实现。
当然,除了Java本身支持的协议之外,我们还可以自己去扩展这个协议,大致只需要两步即可:
-
实现URLConnection,可以通过这个连接读取资源的内容
-
实现URLStreamHandler,通过URLStreamHandler可以获取到URLConnection
不过需要注意的是,URLStreamHandler的实现需要放在sun.net.www.protocol.协议名称
包下,类名必须是Handler
,这也是为什么截图中的实现类名都叫Handler
的原因。
当然如果不放在指定的包下也可以,但是需要实现java.net.URLStreamHandlerFactory
接口。
对于扩展我就不演示了,如果你感兴趣可以自行谷歌一下。
Spring资源管理
虽然Java提供了标准的资源管理方式,但是Spring并没有用,而是自己搞了一套资源管理方式。
1、资源抽象
在Spring中,资源大致被抽象为两个接口
-
Resource:可读资源,可以获取到资源的输入流
-
WritableResource:读写资源,除了资源输入流之外,还可以获取到资源的输出流
Resource
Resource接口继承了InputStreamSource接口,而InputStreamSource接口可以获取定义了获取输入流的方法
WritableResource
WritableResource
继承了Resource
接口,可以获取到资源的输出流,因为有的资源不仅可读,还可写,就比如一些本地文件的资源,往往都是可读可写的
Resource
的实现很多,这里我举几个常见的:
-
FileSystemResource:读取文件系统的资源
-
UrlResource:前面提到的Java的标准资源管理的封装,底层就是通过URL来访问资源
-
ClassPathResource:读取classpath路径下的资源
-
ByteArrayResource:读取静态字节数组的数据
比如,想要通过Spring的资源管理方式来访问前面提到百度首页网络资源,就可以这么写
//构建资源
Resource resource = new UrlResource("http://www.baidu.com");
//获取资源输入流
InputStream inputStream = resource.getInputStream();
如果是一个本地文件资源,那么除了可以使用UrlResource,也可以使用FileSystemResource,都是可以的。
2、资源加载
虽然Resource
有很多实现,但是在实际使用中,可能无法判断使用具体的哪个实现,所以Spring提供了ResourceLoader
资源加载器来根据资源的类型来加载资源。
ResourceLoader
通过getResource
方法,传入一个路径就可以加载到对应的资源,而这个路径不一定是本地文件,可以是任何可加载的路径。
ResourceLoader
有个唯一的实现DefaultResourceLoader
比如对于上面的例子,就可以通过ResourceLoader
来加载资源,而不用直接new具体的实现了
//创建ResourceLoader
ResourceLoader resourceLoader = new DefaultResourceLoader();
//获取资源
Resource resource = resourceLoader.getResource("http://www.baidu.com");
除了ResourceLoader
之外,还有一个ResourcePatternResolver
可以加载资源
ResourcePatternResolver
继承了ResourceLoader
通过ResourcePatternResolver
提供的方法可以看出,他可以加载多个资源,支持使用通配符的方式,比如classpath*:
,就可以加载所有classpath的资源。
ResourcePatternResolver
只有一个实现PathMatchingResourcePatternResolver
PathMatchingResourcePatternResolver
3、小结
到这就讲完了Spring的资源管理,这里总结一下本节大致的内容
Java的标准资源管理:
-
URL
-
URLStreamHandler
Spring的资源管理:
-
资源抽象:Resource 、WritableResource
-
资源加载:ResourceLoader 、ResourcePatternResolver
Spring的资源管理在Spring中用的很多,比如在SpringBoot中,application.yml
的文件就是通过ResourceLoader加载成Resource,之后再读取文件的内容的。