Spring资源抽象Resource
JDK操纵底层资源基本就是 java.net.URL 、java.io.File 、java.util.Properties这些。取资源基本是根据绝对路径或当前类的相对路径来取。从类路径或Web容器上下文中获取资源的时候也不方便。Resource接口提供了更强大的访问底层资源的能力。
废话不多说,看源码之前先来看一下Resource的类结构。
一、类结构
一、Resource接口
如图,Resouce接口并不是一个根接口,它继承了一个简单的父接口 InputStreamSource,这个接口只有一个方法,用以返回一个输入流:
InputStream getInputStream() throws IOException;
来,直接上Resource接口的源码,中文是我根据英文注释自己翻译的,如下:
public interface Resource extends InputStreamSource { boolean exists(); // 资源是否存在
boolean isReadable(); // 资源是否可读
boolean isOpen(); // 资源所代表的句柄是否被一个stream打开了
URL getURL() throws IOException; // 返回资源的URL的句柄
URI getURI() throws IOException; // 返回资源的URI的句柄
File getFile() throws IOException; // 返回资源的File的句柄
long contentLength() throws IOException; // 资源内容的长度
long lastModified() throws IOException; // 资源最后的修改时间
Resource createRelative(String relativePath) throws IOException; //根据资源的相对路径创建新资源
String getFilename(); // 资源的文件名
String getDescription(); //资源的描述
}
这个没什么好说的,继续!
二、抽象类AbstractResource
对于任何的接口而言,这个直接抽象类是重中之重,里面浓缩了接口的大部分公共实现。翻译后如下:


结论:
1、增加了一个方法,protected File getFileForLastModifiedCheck() throws IOException,要求子类实现,如果子类未实现,那么直接返回资源文件。这个方法的具体作用,后面再看实现类。
2、方法 contentLength() ,是一个很比较重量级的方法,它通过将资源全部读取一遍来判断资源的字节数。255字节的缓冲数组来读取。子类一般会重写。(调整一下缓冲数组的大小?)
3、getDescription() 是这个抽象类唯一没有实现的接口方法,留给子类去实现,资源文件默认的equals()、hashCode() 都通过这个来判断。
4、InputStreamSource这个祖先接口的唯一方法 getInputStream()也没有被实现,留给子类。
三、Resource的子接口ContextResource和WritableResource
这两个接口继承于Resource,拥有Resource的全部方法。其中,ContextResource接口增加了一个方法:
String getPathWithinContext(); // 返回上下文内的路径
这个方法使得它的实现类有了返回当前上下文路径的能力。
WritableResource接口增加了2个方法:
boolean isWritable(); // 是否可写
OutputStream getOutputStream() throws IOException; //返回资源的写入流
这个方法使得它的实现类拥有了写资源的能力。
四、重要的抽象类AbstractFileResolvingResource
这个抽象类继承自AbstractResource,重写了AbstractResource的大部分方法。
public abstract class AbstractFileResolvingResource extends AbstractResource { @Override
public File getFile() throws IOException { // 通过资源的URL得到资源本身,是文件就返回文件,否则返回描述
URL url = getURL();
if (url.getProtocol().startsWith(ResourceUtils.URL_PROTOCOL_VFS)) {
return VfsResourceDelegate.getResource(url).getFile();
}
return ResourceUtils.getFile(url, getDescription());
} @Override
protected File getFileForLastModifiedCheck() throws IOException { //从<压缩文件地址>中获取文件
URL url = getURL();
if (ResourceUtils.isJarURL(url)) {
URL actualUrl = ResourceUtils.extractJarFileURL(url);
if (actualUrl.getProtocol().startsWith(ResourceUtils.URL_PROTOCOL_VFS)) {
return VfsResourceDelegate.getResource(actualUrl).getFile();
}
return ResourceUtils.getFile(actualUrl, "Jar URL");
}
else {
return getFile();
}
} protected File getFile(URI uri) throws IOException { // 通过资源uri获取文件
if (uri.getScheme().startsWith(ResourceUtils.URL_PROTOCOL_VFS)) {
return VfsResourceDelegate.getResource(uri).getFile();
}
return ResourceUtils.getFile(uri, getDescription());
} @Override
public boolean exists() { //判断资源是否存在,如果是文件Url,直接获取文件判断,否则,建立连接来判断。
try {
URL url = getURL();
if (ResourceUtils.isFileURL(url)) {
// Proceed with file system resolution...
return getFile().exists();
}
else {
// Try a URL connection content-length header...
URLConnection con = url.openConnection();
ResourceUtils.useCachesIfNecessary(con);
HttpURLConnection httpCon =
(con instanceof HttpURLConnection ? (HttpURLConnection) con : null);
if (httpCon != null) {
httpCon.setRequestMethod("HEAD");
int code = httpCon.getResponseCode();
if (code == HttpURLConnection.HTTP_OK) {
return true;
}
else if (code == HttpURLConnection.HTTP_NOT_FOUND) {
return false;
}
}
if (con.getContentLength() >= 0) {
return true;
}
if (httpCon != null) {
// no HTTP OK status, and no content-length header: give up
httpCon.disconnect();
return false;
}
else {
// Fall back to stream existence: can we open the stream?
InputStream is = getInputStream();
is.close();
return true;
}
}
}
catch (IOException ex) {
return false;
}
} @Override
public boolean isReadable() { // 是否可读
try {
URL url = getURL();
if (ResourceUtils.isFileURL(url)) {
// Proceed with file system resolution...
File file = getFile();
return (file.canRead() && !file.isDirectory());
}
else {
return true;
}
}
catch (IOException ex) {
return false;
}
} @Override
public long contentLength() throws IOException {
URL url = getURL();
if (ResourceUtils.isFileURL(url)) {
// Proceed with file system resolution...
return getFile().length();
}
else {
// Try a URL connection content-length header...
URLConnection con = url.openConnection();
ResourceUtils.useCachesIfNecessary(con);
if (con instanceof HttpURLConnection) {
((HttpURLConnection) con).setRequestMethod("HEAD");
}
return con.getContentLength();
}
} @Override
public long lastModified() throws IOException {
URL url = getURL();
if (ResourceUtils.isFileURL(url) || ResourceUtils.isJarURL(url)) {
// Proceed with file system resolution...
return super.lastModified();
}
else {
// Try a URL connection last-modified header...
URLConnection con = url.openConnection();
ResourceUtils.useCachesIfNecessary(con);
if (con instanceof HttpURLConnection) {
((HttpURLConnection) con).setRequestMethod("HEAD");
}
return con.getLastModified();
}
} /**
* Inner delegate class, avoiding a hard JBoss VFS API dependency at runtime.
*/
private static class VfsResourceDelegate { public static Resource getResource(URL url) throws IOException {
return new VfsResource(VfsUtils.getRoot(url));
} public static Resource getResource(URI uri) throws IOException {
return new VfsResource(VfsUtils.getRoot(uri));
}
} }
这个抽象类的子类都需要重写继承自AbstractResource的getURL()方法。因为绝大多数方法都依赖这个方法,进行资源在url上的操作。
所以在查看资源情况的时候,需要根据url建立连接来查看。
Spring资源抽象Resource的更多相关文章
- spring 资源访问
spring 资源访问 Resource resource=null; //访问网络资源 resource=new UrlResource("file:bool.xml"); // ...
- Spring资源加载器抽象和缺省实现 -- ResourceLoader + DefaultResourceLoader(摘)
概述 对于每一个底层资源,比如文件系统中的一个文件,classpath上的一个文件,或者一个以URL形式表示的网络资源,Spring 统一使用 Resource 接口进行了建模抽象,相应地,对于这些资 ...
- 05.Spring 资源加载 - Resource
基本概念 Spring 把所有能记录信息的载体,如各种类型的文件.二进制流等都称为资源. 对 Spring 开发者来说,最常用的资源就是 Spring 配置文件(通常是一份 XML 格式的文件). S ...
- Spring 学习笔记 Resource 资源
Spring Resources 概述 在日常程序开发中,处理外部资源是很繁琐的事情,我们可能需要处理 URL 资源.File 资源.ClassPath相关资源等等.并且在 java 中 Java . ...
- 攻城狮在路上(贰) Spring(三)--- Spring 资源访问利器Resource接口
Spring为了更好的满足各种底层资源的访问需求.设计了一个Resource接口,提供了更强的访问底层资源的能力.Spring框架使用Resource装载各种资源,包括配置文件资源.国际化属性文件资源 ...
- Spring 资源文件处理
Java中,不同来源的资源抽象成URL,通过注册不同的handler(URLStreamHandler)来处理不同来源的资源的读取逻辑.一般handler的类型使用不同的前缀(协议,protocal) ...
- spring资源加载结构解析
1.spring中资源加载使用resources的原因? 在java将不同资源抽象成url,然后通过注册不同的hander来处理不同读取逻辑,一般hander使用协议的前缀来命名,如http,jar, ...
- 170324、Spring 处理器和Resource
1.Spring 框架允许开发者使用两种后处理器扩展 IoC 容器,这两种后处理器扩展 IoC 容器,这两种后处理器可以后处理 IoC 容器本身,或对容器中所有的 Bean 进行后处理.IoC 容器还 ...
- Spring中的Resource
Spring中的资源定义:Resource此接口的全名为:org.springframework.core.io.Resource比较常用的资源定义的实现类为:1.ClassPathResource ...
随机推荐
- 洛谷P2251 质量检测
题目背景 无 题目描述 为了检测生产流水线上总共N件产品的质量,我们首先给每一件产品打一个分数A表示其品质,然后统计前M件产品中质量最差的产品的分值Q[m] = min{A1, A2, ... Am} ...
- finally不管有没有错都会运行 finally 块用于清除 try 块中分配的任何资源,以及运行任何即使在发生异常时也必须执行的代码
finally 块用于清除 try 块中分配的任何资源,以及运行任何即使在发生异常时也必须执行的代码
- javafx drag
public class EffectTest extends Application { @Override public void start(Stage stage) { stage.setTi ...
- SQL 锁 lock
http://www.cnblogs.com/huangxincheng/p/4292320.html 关于sql 中的锁. 1 排他锁 sql中在做 insert update delete 会存在 ...
- jq实现回车键执行方法
$(function(){ $(document).keypress(function (e){ if(e.keyCode == 13){ //执行你想执行的方法,keyCode代表不同的按键 } } ...
- px、em、rem、vw、vh、vm、rpx这些单位的
px是像素 em是参考父元素的font-size的倍数 rem是参考根元素的font-size 常用于响应式,一般会让html的font-size:625%,body的大小为.16rem.这样1rem ...
- angular入门(基础篇)
一.什么是AngularJs? AngularJs是一个JavaScript框架,通过指令扩展了HTML,并且通过表达式绑定数据到HTML. AngularJs使得开发现代的单页面应用程序(SPA:S ...
- 【CS Round #39 (Div. 2 only) C】Reconstruct Sum
[Link]:https://csacademy.com/contest/round-39/task/reconstruct-sum/ [Description] 给你一个数字S; 让你找有多少对A, ...
- 【Android】利用安卓的数据接口、多媒体处理编写内存卡Mp3播放器app
通过调用安卓的MediaPlayer能够直接完毕Mp3等主流音频的播放,同一时候利用ContentResolver与Cursor能够直接读取安卓内在数据库的信息.直接获取当前sdcard中全部音频的列 ...
- monkey基础知识(二)