spring为资源访问提供了一个Resource接口,该接口提供了更强的资源访问能力。
主要方法:
最后两个方法通常无需使用,仅在通过简单方式访问无法实现时,Resource才提供传统的资源访问功能。
Resource接口本身不提供任何底层资源的实现逻辑,针对不同的底层资源,Spring提供不同的Resource实现类。这是典型的策略模式。
ServletContextResource
访问应用相关资源
ServletContextResource
类访问WebContext下相对路径下的资源。构造方法:
public ServletContextResource(ServletContext servletContext, String path)
使用
ServletContextResource
访问资源无需关心资源是否被解压缩出来,直接存放在jar中的资源也可以通过servlet容器访问。
InputStreamResource
用来访问二进制输入流资源,只有当没有合适的Resource实现时,才考虑使用InputStreamResource
,通常优先考虑使用ByteArrayResource
,或者基于文件的Resource实现。
InputStreamResource
是一个总被打开的Resource,所以isOpen()方法总是返回true。因此需要多次读取某个流,就不要使用它。个别情况下可以使用
InputStreamResource
例如从数据库中读取一个Blob对象,程序需要获取该Blob对象内容,就可以先通过Blob的getBinaryStream()方法获取二进制输入流,再将这个流包装成Resource对象,然后就个可以通过Resource对象来访问Blob对象所包含的资源了。
InputStreamResource
的效率并不好。
UrlResource res = new UrlResource("file:///d:GenreUserId/1.txt");
UrlResource虽然是为了网络资源设计的,但通过使用file:前缀也可以访问本地磁盘资源。
常用的前缀:
- file:
- http:
- ftp:
- classpath:
需要注意file:
前缀的用法
ApplicationContext ctx = new FileSystemXmlApplicationContext("bean.xml");
ApplicationContext ctx = new FileSystemXmlApplicationContext("/bean.xml");
上面两行代码读取了相同的配置资源文件。
问题是:如果程序中明明采用的一个是绝对路径、一个相对路径,为什么执行效果没有任何区别?
产生问题的原因:当 FileSystemXmlApplicationContext
作为 ResourceLoader
使用时,它会发生变化,FileSystemApplicationContext
会简单地让所有绑定的 FileSystemResource
实例把绝对路径都当成相对路径处理,而不管是否以斜杠开头,所以上面两行代码的效果是完全一样的。
如果程序中需要访问绝对路径,则不要直接使用 FileSystemResource
或 FileSystemXmlApplicationContext
来指定绝对路径。建议强制使用 file:
前缀来区分相对路径和绝对路径,例如如下两行代码:
ApplicationContext ctx = new FileSystemXmlApplicationContext("file:bean.xml");
ApplicationContext ctx = new FileSystemXmlApplicationContext("file:/bean.xml");
上面第一条语句访问相对路径下的 bean.xml,第二条语句访问绝对路径下 bean.xml。相对路径以当前工作路径为路径起点,而绝对路径以文件系统根路径为路径起点。
ResourceLoader
接口、ResourceLoaderAware
接口ResourceLoader只有一个方法:
Resource getResource(String location)
ApplicationContext
的实现类都实现了ResourceLoader
接口。
因此ApplicationContext
可以直接获得Resource
实例, 进而拥有加载资源的能力。
Resource res = ctx.getResource("1.txt");
通过ApplicationContext
获取资源的具体实现类由创建ApplicationContext
时使用的实现类决定。也可以使用前缀来强制指定使用那种实现类来读取资源。
ApplicationContext确定资源访问策略有两种方式:
* 使用ApplicationContext实现类指定访问策略。
* 使用前缀指定访问策略。
前缀访问可以使用classpath*:
来加载多个XML配置文件。指定的文件也可以使用通配符的形式配置,如 ClassPathXmlApplicationContext("beans*.xml")
。通配符也可以和classpath*:
一起使用。
ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath*:spring-*.xml");
注意: classpath*:
前缀仅仅对ApplicationContext
有效。classpath*:
不可以用于Resource
,使用classpath*:
一次性访问多个资源是行不通的。
public class Student{
private int age;
private String name;
Resource resource;
//getter and setter ...
}
<bean id="student" class="com.erick.d1.hello.Student" >
<property name="name" value="cat" />
<property name="age" value="99" />
<property name="resource" value="classpath:user.properties" />
bean>