Spring - Resources

Java 標準所提供的訪問資源的類(如 java.net.URL、java.io.File 等)並不能很好地知足各類底層資源的訪問需求,好比缺乏從類路徑或者 Web 容器的上下文中獲取資源的操做類。java

 

Resource 接口

Spring 提供了一個 Resource 接口,它爲應用提供了更強的底層資源訪問能力。Resource 接口主要的幾個方法:spring

  • exists():返回一個 boolean 值,表示資源是否存在。
  • isOpen():返回一個 boolean 值,表示資源是否打開。
  • getInputStream():放資源對應的輸入流。
  • getURL():若是底層資源能夠表示成 URL,則返回對應的 URL對象。
  • getFile():若是底層資源對應一個文件,則返回對應的 File 對象。
  • getDescription():返回資源的描述。當處理資源出錯時,資源的描述會用於錯誤信息的輸出。通常來講,資源的描述是一個徹底限定的文件名稱或當前資源的真實 URL。

 

內置的 Resource 實現

UrlResource

UrlResource 封裝了 java.net.URL,它使用戶可以訪問任何能夠經過 URL 表示的資源,如 HTTP 資源、FTP 資源、文件系統資源等。例:服務器

try {
    Resource resource = new UrlResource("http://example.com/");
    InputStream inStream = resource.getInputStream();
    String content = IOUtils.toString(inStream);
    System.out.println(content);
} catch (IOException e) {
    e.printStackTrace();
}

ClassPathResource

ClassPathResource 能夠訪問類路徑下的資源,資源以相對於類路徑的方式表示。例:app

try {
    Resource resource = new ClassPathResource("conf/jdbc.properties");
    InputStream inStream = resource.getInputStream();
    String content = IOUtils.toString(inStream);
    System.out.println(content);
} catch (IOException e) {
    e.printStackTrace();
}

FileSystemResource

FileSystemResource 能夠訪問文件系統資源,資源以文件系統路徑的方式表示。例:ide

try {
    Resource resource = new FileSystemResource("D:/test.txt");
    InputStream inStream = resource.getInputStream();
    String content = IOUtils.toString(inStream);
    System.out.println(content);
} catch (IOException e) {
    e.printStackTrace();
}

ServletContextResource

ServletContextResource 是爲了訪問 Web 容器上下文中的資源而提供的類,負責以相對於 Web 應用根目錄的路徑加載資源。它支持以流和 URL 的方式訪問,在 WAR 解包的狀況下,也能夠經過 File 方式訪問。該類還能夠直接從 JAR 包中訪問資源。例:url

@WebServlet(name = "helloServlet", urlPatterns = { "/hello.png" })
public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Resource resource = new ServletContextResource(req.getServletContext(), "/image/1.png");        
        InputStream inStream = resource.getInputStream();
        byte[] byteArray = IOUtils.toByteArray(inStream);
        resp.getOutputStream().write(byteArray);
    }
}

InputStreamResource

InputStreamResource 能夠訪問以輸入流返回表示的資源。spa

ByteArrayResource

ByteArrayResource 能夠訪問以二進制數值表示的資源。.net

PathResource

PathResource 是 Spring 4.x 提供的讀取資源文件的新類。Path 封裝了 java.net.URL、java.nio.file.Path、文件系統資源,它使用戶可以訪問任何能夠經過 URL、Path、系統文件路徑表示的資源。code

 

ResourceLoader

爲了訪問不一樣類型的資源,必須使用相對應的 Resource 實現類,這個是比較麻煩的。是否能夠在不顯示使用 Resource 實現類的狀況下,僅經過資源地址的特殊標識就能夠訪問相應的資源呢?Spring 提供了一個強大的加載資源的機制,不但可以經過 「classpath:」、「file:」 等資源地址前綴識別不一樣的資源類型,還支持 Ant 風格帶通配符的資源地址。xml

資源地址表達式

地址前綴 對應的資源類型 示例
 classpath: 從類路徑中加載資源,classpath: 和 classpath:/ 是等價的,都是相對於類的根路徑。資源文件能夠在標準的系統文件中,也可在 JAR 或 ZIP 的類包中。  classpath:com/huey/hello/mapper/UserMapper.xml
 file: 從文件系統目錄中裝載資源,可採用絕對或相對路徑。  file:/config/jdbc.properties
 http:// 從 HTTP 服務器中裝載資源。  http://www.example.com/resource/beans.xml
 ftp:// 從 FTP 服務器中裝載資源。  ftp://www.example.com/resource/beans.xml
 (none) 根據 ApplicationContext 的具體實現採用對應類型的 Resource。  com/huey/hello/config/beans.xml

與 「classpath:」 對應的還有一種 「classpath*:」 前綴。假設有多個 JAR 包或文件系統類路徑都擁有一個相同的包名(如 com.huey)。「classpath:」 只會在第一個加載的 com.huey 包的類路徑下查找,而 「classpath*:」 會掃描因此這些 JAR 包及類路徑下出現的 com.huey 類路徑。這對於分模塊打包的應用很是有用。假設一個名爲 helloworld 的應用共分紅 3 個模塊,一個模塊對應一個配置文件,分別是 module1.xml、module2.xml 及 module3.xml,都放到 spring/config 目錄下,每一個模塊單獨打成 JAR 包。使用 「classpath*:spring/config/module*.xml」 能夠成功加載這 3 個配置文件,而使用 「classpath:spring/config/module*.xml」 只會加載一個模塊的配置文件。

Ant 風格的資源地址支持 3 種通配符:

  • ?:匹配文件名中的一個字符。
  • *:匹配文件名中的任意字符。
  • **:匹配任意層路徑。

資源加載器

Spring 定義了一個資源加載的接口,並提供實現類。

ResourceLoader 接口僅有一個 getResource(String location) 方法,能夠根據一個資源地址加載文件資源。不過,資源地址僅支持帶資源類型前綴的表達式,不支持 Ant 更改的資源路徑表達式。ResourcePatternResolver 擴展 ResourceLoader 接口,定義了一個新的接口方法 getResources(String locationPattern),該方法支持帶資源類型前綴及 Ant 風格的資源路徑表達式。PathMatchingResourcePatternResolver 是 Spring 提供的標準實現類。例:

ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
try {
    Resource[] resources = resolver.getResources("classpath*:conf/spring/*-beans.xml");
    for (Resource resource : resources) {
        System.out.println(resource.getDescription());
    }
} catch (IOException e) {
    e.printStackTrace();
}

ClassPathXmlApplicationContext & FileSystemXmlApplicationContext

Spring 裏的全部應用上下文都實現了 ResourcePatternResolver 接口,所以,全部的應用上下文均可以經過 getResource()、getResources() 方法獲取 Resource 實例。當經過 ClassPathXmlApplicationContext 實例調用 getResource 或 getResources 方法時,當沒有顯示指定資源前綴時,則將路徑解析爲類路徑,同時返回的 Resource 實例是 ClasspathResource 類型;FileSystemXmlApplicationContext 則將路徑解析爲文件系統路徑,返回的 Resource 實例是 FileSystemResource 類型。當以資源路徑爲參數構造 ClassPathXmlApplicationContext 和 FileSystemXmlApplicationContext 實例時也是同樣的。

相關文章
相關標籤/搜索