传统的Java资源文件的访问通过JDK中的File、URL类难以满足各种不同需求的资源加载,这里有Spring中设计的Resource接口提供更加强大的访问底层资源的能力。
spring 中定义了资源接口,部分类关系如下:
InputStreamSource接口方法:InputStream getInputStream() throws IOException;:返回资源对应的输入流
下面是Resource接口的主要方法:
- boolean exists():资源是否存在
- boolean isOpen():资源是否打开
- URL getURL() throws IOException:如果底层资源可以表示成URL,该方法返回对应的URL对象
- File getFile() throws IOException:如果底层资源对应一个文件,该方法返回对应的File对象
createRelative(String relativePath) 在当前资源的相对路径创建新的资源对象。
WritableResource:该接口提供可供写入的资源。该接口继承自Resource,并提供自身的两个写入方法:
boolean isWritable();
OutputStream getOutputStream()throwsIOException;
Resource实现类有很多,常见的具体实现类如下:
- ByteArrayResource:二进制数组表示的资源
- ClassPathResource:类路径下的资源,资源以相对于类路径的方式表示
- :文件系统资源,资源以文件系统路径的方式表示
- InputStreamResource:以输入流返回表示的资源
- ServletContextResource:为访问Web容器上下文中的资源而设计的类,负责以相对于Web应用程序根目录的路径加载资源,它支持以流和URL的方式访问,在WAR解包的情况下,也可以通过File的方式访问,还可以直接从JAR包中访问资源
- URLResource:Url封装了java.net.URL,它使用户能够访问任何可以通过URL表示的资源,如文件系统的资源、HTTP资源、FTP资源
如下分别通过FileSystemResource和ClassPathResource访问同一个文件资源:
import java.io.IOException;
import java.io.InputStream;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
public class FileSourceExample {
public static void main(String[] args) {
try {
String filePath = "D:/Spring/WebRoot/WEB-INF/classes/conf/file1.txt";
Resource res1 = new FileSystemResource(filePath);
Resource res2 = new ClassPathResource("conf/file1.txt");
InputStream ins1 = res1.getInputStream();
InputStream ins2 = res2.getInputStream();
System.out.println("res1:"+res1.getFilename());
System.out.println("res2:"+res2.getFilename());
} catch (IOException e) {
e.printStackTrace();
}
}
}
获取到资源后,可以通过getFileName()获取方法名,通过getFile()获取资源对应的File文件,通过getInputStream()直接获取文件的输入流,还可通过createRelative(String relativePath)在资源相对地址上创建新的文件。
如下是在Web应用中通过ServletContextResource以相对于Web应用根目录的方式访问文件资源:
resource.jsp
<%@ 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"/>
<jsp:directive.page import="org.springframework.web.util.WebUtils"/>
<%
Resource res3 = new ServletContextResource(application,"/WEB-INF/classes/conf/file1.txt");
out.print(res3.getFilename()+"<br/>");
out.print(WebUtils.getTempDir(application).getAbsolutePath());
%>
可以通过EncodedResource对资源进行编码,保证资源内容操作的正确性,如下:
package com.baobaotao.resource;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.EncodedResource;
import org.springframework.util.FileCopyUtils;
public class EncodedResourceExample {
public static void main(String[] args) throws Throwable {
Resource res = new ClassPathResource("conf/file1.txt");
EncodedResource encRes = new EncodedResource(res,"UTF-8");
String content = FileCopyUtils.copyToString(encRes.getReader());
System.out.println(content);
}
}
spring中资源加载的地址前缀如下:
- classpath:表示从类路径加载资源
- file:使用UrlResource从文件系统目录中装载资源,可采用绝对或相对路径
- http:// :从Web服务器中装载资源
- ftp:// : 从FTP服务器中装载资源
其中,classpath:和classpath*:的区别在于classpath*:会扫描所有类路径下出现的资源,而classpath只会在第一个加载的包下查找,即就是只加载一个资源文件。