Java 標準所提供的訪問資源的類(如 java.net.URL、java.io.File 等)並不能很好地知足各類底層資源的訪問需求,好比缺乏從類路徑或者 Web 容器的上下文中獲取資源的操做類。java
Spring 提供了一個 Resource 接口,它爲應用提供了更強的底層資源訪問能力。Resource 接口主要的幾個方法:spring
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 能夠訪問類路徑下的資源,資源以相對於類路徑的方式表示。例: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 能夠訪問文件系統資源,資源以文件系統路徑的方式表示。例: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 是爲了訪問 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 能夠訪問以輸入流返回表示的資源。spa
ByteArrayResource 能夠訪問以二進制數值表示的資源。.net
PathResource 是 Spring 4.x 提供的讀取資源文件的新類。Path 封裝了 java.net.URL、java.nio.file.Path、文件系統資源,它使用戶可以訪問任何能夠經過 URL、Path、系統文件路徑表示的資源。code
爲了訪問不一樣類型的資源,必須使用相對應的 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(); }
Spring 裏的全部應用上下文都實現了 ResourcePatternResolver 接口,所以,全部的應用上下文均可以經過 getResource()、getResources() 方法獲取 Resource 實例。當經過 ClassPathXmlApplicationContext 實例調用 getResource 或 getResources 方法時,當沒有顯示指定資源前綴時,則將路徑解析爲類路徑,同時返回的 Resource 實例是 ClasspathResource 類型;FileSystemXmlApplicationContext 則將路徑解析爲文件系統路徑,返回的 Resource 實例是 FileSystemResource 類型。當以資源路徑爲參數構造 ClassPathXmlApplicationContext 和 FileSystemXmlApplicationContext 實例時也是同樣的。