资源访问接口 Resource
为了弥补 JDK 提供的资源访问类(java.net.URL,java.io.File等)缺少从类路径或Web容器的上下文中获取资源的能力,Spring 提供了
Resouce 接口和一系列的实现类来是增强对不同类型资源的访问能力;
Resource 接口主要的
方法:
boolean exists() | 资源是否存在; |
boolean isOpen() | 资源是否打开; |
boolean isReadable() | 资源是否可读; |
URL getURL() | 获取该资源的 URL 对象; |
File getFile() | 获取该资源的 File 对象; |
String getFileName() | 获取资源File名; |
InputStream getInputStream() | 获取该资源的输入流; |
OutputStream getOutputStream() | 获取该资源的输出流; |
Resource createRelative(String relativePath) | 在该资源的相对路径创建一个新资源 |
Resource 的分别对于不同的资源类型有具体的
实现类:
ByteArrayResource | 二进制数组表示的资源,这种资源可以直接在内存中通过程序构造; |
ClassPathResource | 类路径下的资源,资源以相对于类路径的方式表示 |
FileSystemResource | 文件系统资源,资源以文件系统路径表示; |
UrlResource | 可以访问通过URL表示的资源,如文件系统资源,HTTP资源,FTP资源 |
InputStreamResource | 以输入流表示的资源 |
PathResource | Spring4.0 提供的读取资源的新类,可以访问任何可以通过 URL,Path,系统文件路径表示的资源(可以用于代替FileSystemResource,UrlResource) |
ServletContextResource | 可以访问Web容器上下文中的资源,以相对于Web应用根目录路径加载的资源;支持以流和URL的方式访问;可以访问 WAR 和 JAR 中的资源;(以webapp为起点) |
使用示例
示例的文件结构:
test_spring
└src
└ main
├ java
| └com.assad.resource
| └ FileSourceSample.java
├ resources
| └ sample
| └ resourceSample.txt //资源1
└ webapp
├ WEB-INF
| └ sample
| └ resourceSample2.txt //资源2
└ resource.jsp
FileSourceSample.java 访问资源 1
package com.assad.resource;
public class FileSourceSample {
public static void main(String[] args){
//PathResource 以文件系统绝对路径方式加载资源 (FileSystemResource同理)
Resource res1 = new PathResource("C:/Al-assad/workplace/workplace-IDEA/testSpring/src/main/resources/sample/resouceSample.txt");
System.out.println(FileCopyUtils.copyToString(new InputStreamReader(res1.getInputStream())));
//ClassPathResource 以类路径的方式访问
Resource res2 = new ClassPathResource("/sample/resourceSample.txt");
System.out.println(FileCopyUtils.copyToString(new InputStreamReader(res2.getInputStream())));
}
}
resource.jsp 访问资源 2
<% page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>
<jsp:directive.page import="org.springframework.web.context.support.ServletContextResource"/>
<jsp:directive.page import="org.springframework.core.io.Resource"/>
<%
//ServletContextResource 以相对于Web应用根目录的路径加载资源(即 webapp/目录下)
Resource res3 = new ServletContextResource(application,"/WEB-INF/sample/resourceSample2.txt");
out.print(res3.getFilename());
%>
对资源进行重新编码
资源加载时采用系统默认编码读取资源内容,可以通过 EncodedResource 对资源强制指定编码读取;
Resource res = new ClassPathResource("/sample/resourceSample.txt");
Encoded enRes - new Encodedresource(res,"UTF-8");
String content = FileCopyUtils.copyToString(enRes.getReader());
资源表达式&资源加载器
在使用以上的Resouce实现类加载资源时,必须先判断资源类型再选择相应的资源类型,比较麻烦,Spring 提供了强大资源地址表达式来识别不同的资源类型,同时还支持Ant风格带通配符的资源地址;
资源地址表达式
资源表达式前缀:
地址前缀 | 示例 | 对应的资源类型 |
classpath: | classpath:com/assad/beanfactory/beans.xml classpath:sample/resourceSample.txt | 从类路径中加载,相对于类的根路径,等同于classpath:/,资源文件可以存在于标准的文件系统中,也可以存在JAR或ZIP中; 类似于ClassPathResource |
file: | file:c:/bin/myprogram/beans.xml | 使用UrlResource从系统目录中装载资源 |
http:// | http://assad.site/resource/beans.xml | 使用UrlResource从Web服务器中装载资源 |
ftp:// | ftp://assad.site/resource/beans.xml | 使用UrlResource从FTP服务器中装载资源 |
无前缀 | com/assad/beanfactory/beans.xml sample/resourceSample.txt | 根据ApplicationContext的具体实现采用对应类型的Resource |
classpath*: 前缀:用于加载所有符合该路径的包下的资源,比如有多个JAR或文件系统含有同一个包名 com.assad,“classpath:com/assad/...” 只会加载符合条件的第一个包名下的资源,“classpath*:com/assad/...”会加载所有符合条件包名下的资源;
Ant风格的资源表达式
Ant 风格的资源地址支持一下3种通配符
? | 匹配文件名中的一个字符 |
* | 匹配文件名中任意数量的字符 |
** | 匹配多层路径 |
资源加载器
Spring 定义了一套资源加载的接口,并提供了实现类,用于支持以上的资源地址表达式;
ResourceLoader 接口,只是实现了 getResource(String location) 方法,可以根据一个资源地址加载资源(不过不支持Ant风格资源地址表达式);
ResourcePatternResolver 接口拓展了 ResourceLoader ,定义了一个接口方法 getResource
(String locationPattern),支持Ant风格的资源地址表达式;
PathMatchingResourcePatternResolver 是 Spring 提供的标准实现类;
以下例子示例:
//加载单一资源
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource res = resolver.getResource("classpath:sample/resouceSample.txt");
System.out.println(FileCopyUtils.copyToString(new InputStreamReader (res.getInputStream())));
//加载resources/sample/下的所有xml文件;
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource res[] = resolver.getResources("classpath:sample/**/*.xml");