传统的Java资源文件的访问通过JDK中的File、URL类难以满足各种不同需求的资源加载,这里有Spring中设计的Resource接口提供更加强大的访问底层资源的能力。

spring 中定义了资源接口,部分类关系如下:

resources文件夹 输出_java

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只会在第一个加载的包下查找,即就是只加载一个资源文件。