1. 程式人生 > >this.class.getClassLoader().getResourceAsStream與this.class.getResourceAsStream

this.class.getClassLoader().getResourceAsStream與this.class.getResourceAsStream

isarray admin comm ext 修改 string class template 沒有

本文轉自:http://xixinfei.iteye.com/blog/1256291

this.getClass().getClassLoader().getResource("template");
  首先,調用對象的getClass()方法是獲得對象當前的類類型,這部分數據存在方法區中,而後在類類型上調用getClassLoader()方法是得到當前類型的類加載器,我們知道在Java中所有的類都是通過加載器加載到虛擬機中的,而且類加載器之間存在父子關系,就是子知道父,父不知道子,這樣不同的子加載的類型之間是無法訪問的(雖然它們都被放在方法區中),所以在這裏通過當前類的加載器來加載資源也就是保證是和類類型同一個加載器加載的。


最後調用了類加載器的getResourceAsStream()方法來加載資源。

====================================

JAVA運行時,首先會在指定的類路徑下(classpath路徑下)搜索JAVA編譯後的字節碼文件(class文件),然後通過類加載器加載到虛擬機中。 DBConn.class.getClassLoader().getResourceAsStream("database.properties") 1、DBConn.class得到表示DBConn類的Class對象,請參照JDK中對Class的說明http://wenku.baidu.com/view/1fa5e8ebe009581b6bd9ebe1.html。
2、通過Class的getClassLoader方法取得加載DBConn類的類加載器對象ClassLoader。 3、調用ClassLoader的getResourceAsStream方法從類加載路徑取得文件的輸入流(會通過當前的ClassLoader的findResource方法查找指定文件),請參照:http://download.oracle.com/javase/1.5.0/docs/api/java/lang/ClassLoader.html#getResourceAsStream%28java.lang.String%29。


====================================

下面的JdbcUtils.class後面少了個()嗎?應該是都可以

Properties prop = new Properties();
prop.load(JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties"));
String driver = prop.getProperty("driver");
Class.forName(driver);

====================================

  1. 關於ClassName.class.getClassLoader的幾點說明.
  2. 經常希望通過ClassName.class.getClassLoader().getResourceAsStream(““)來取得properties文件.通常:ClassName.class.getClassLoader().getResourceAsStream(““)取得的是WEB-INF的下級目錄,比如ClassName.class.getClassLoader().getResourceAsStream(“db.properties“).在Tomcat中,可以通過增加”../”來取得上層目錄,即WEB-INF目錄,這樣就可以把properties放在WEB-INF中統一管理。但是WLS不識別”../”。
  3. 另外一種土辦法,就是不返回classLoader,直接ClassName.class.getResourceAsStream()。然後通過多個”../”(小於6個)來返回相應的上級目錄。
  4. 當然,如果類擴展了HttpServlet,可以通過getServletContext().getRealPath("/")來取得Web部署目錄的絕對路徑。

====================================

因此,直接調用 this.getClass().getResourceAsStream(String name);獲取流,靜態化方法中則使用ClassLoader.getSystemResourceAsStream(String name); 。

====================================

在JDK中,getResourceAsStream是這樣定義的:查找具有給定名稱的資源。查找與給定類相關的資源的規則是通過定義類的 class loader 實現的。
因為我是用txt文件當作字典,它存在一個叫dict.aspactword的包下,這樣一來,編譯後的文件會儲存在classPath下,而不是在src下,在動態向字典添加詞的時候,classPath下的txt字典沒有改變,相對在getResourceAsStream的時候,拿到的自然不是最新的字典,由此感嘆,在classPath下如果有不需要改變的文件,在讀取時用getResourceAsStream可以保持系統良好的統一性和可移植性,但是在需要改變它們的時候,一定註意修改的路徑是classPath下的文件,否則就直接用文件系統的位置來維護你所需要的文件吧

============================================================================================================

常見的有以下兩種獲取資源文件的方法:

方法一: App.class.getClassLoader().getResourceAsStream(String name)

Returns an input stream for reading the specified resource.

The search order is described in the documentation for getResource(String).

默認從classpath中找文件,name不能帶“/”,否則會拋空指針

方法二: App.class.getResourceAsStream(String name)

查找資源通過給定名稱,查詢資源的規則與給定的類的class load來實現,這個方法由類的loader來執行,如果這個類由bootstrap加載,那麽方法由ClassLoader.getSystemResourceAsStream代理執行。

代理之前,絕對的資源名稱通過傳入的name參數以下算法進行構造:

如果name以"/"開頭,那麽絕對路徑是/後邊跟的名字

如果name不是以"/"開頭,那麽絕對路徑是package名"."換成“/”以後再加name,例如:

com.abc.App就是/com/abc/App/name

============================================================================================================

另,可參考另一篇文章:Class.getResource和ClassLoader.getResource的區別分析

在Java中獲取資源的時候,經常用到Class.getResource和ClassLoader.getResource,本文給大家說一下這兩者方法在獲取資源文件的路徑差異。
Class.getResource(String path)
path不以‘/‘開頭時,默認是從此類所在的包下取資源;path以‘/‘開頭時,則是從項目的ClassPath根下獲取資源。在這裏‘/‘表示ClassPath
JDK設置這樣的規則,是很好理解的,path不以‘/‘開頭時,我們就能獲取與當前類所在的路徑相同的資源文件,而以‘/‘開頭時可以獲取ClassPath根下任意路徑的資源。
如下所示的例子:

1 2 3 4 5 6 7 8 public class Test { public static void main(String[] args) { System.out.println(Test.class.getResource("")); System.out.println(Test.class.getResource("/")); } }

運行結果為:
file:/D:/work_space/java/bin/net/swiftlet/
file:/D:/work_space/java/bin/

Class.getClassLoader().getResource(String path)
path不能以‘/‘開頭時,path是指類加載器的加載範圍,在資源加載的過程中,使用的逐級向上委托的形式加載的,‘/‘表示Boot ClassLoader中的加載範圍,因為這個類加載器是C++實現的,所以加載範圍為null。如下所示:

1 2 3 4 5 6 7 8 public class Test { public static void main(String[] args) { System.out.println(Test.class.getClassLoader().getResource("")); System.out.println(Test.class.getClassLoader().getResource("/")); } }

運行結果為:
file:/D:/work_space/java/bin/
null
從上面可以看出:
class.getResource("/") == class.getClassLoader().getResource("")
其實,Class.getResource和ClassLoader.getResource本質上是一樣的,都是使用ClassLoader.getResource加載資源的。下面請看一下jdk的Class源碼:

1 2 3 4 5 6 7 8 9 10 11 public java.net.URL getResource(String name) { name = resolveName(name); ClassLoader cl = getClassLoader0(); if (cl==null) { // A system class. return ClassLoader.getSystemResource(name); } return cl.getResource(name); }

從上面就可以看才出來:Class.getResource和ClassLoader.getResource本質上是一樣的。至於為什麽Class.getResource(String path)中path可以‘/‘開頭,是因為在name = resolveName(name);進行了處理:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 private String resolveName(String name) { if (name == null) { return name; } if (!name.startsWith("/")) { Class c = this; while (c.isArray()) { c = c.getComponentType(); } String baseName = c.getName(); int index = baseName.lastIndexOf(‘.‘); if (index != -1) { name = baseName.substring(0, index).replace(‘.‘, ‘/‘) +"/"+name; } } else {//如果是以"/"開頭,則去掉 name = name.substring(1); } return name; }

this.class.getClassLoader().getResourceAsStream與this.class.getResourceAsStream