轉自:http://blog.csdn.net/myyate/article/details/1793039
今天研究Spring源碼中Resource的時候,用到其工具類ResourceUtils其中的getFile(String resourceLocation)。發現了Class和ClassLoader的這兩個方法。先把我的工程目錄貼到這兒吧,如下圖:
Java代碼如下:
public static String FILE_NAME = "ResourceTest_zh_CN.properties";
public static String ABSOLUTE_PATH =
"E:/project/designpattern/classes/";
public static void main(String[] args) throws Exception {
File file = ResourceUtils.getFile("classpath:" + FILE_NAME);
print(file);
file = ResourceUtils.getFile("file:" + ABSOLUTE_PATH + FILE_NAME);
print(file);
}
public static void print(File file) throws Exception {
System.out.println("======================================================");
System.out.println("class name = " + file.getClass().getName());
System.out.println("file name = " + file.getName());
System.out.println("file exists? = " + file.exists());
System.out.println("file absolute path = " + file.getAbsolutePath());
}
}
以上都是運行結果正確的,輸出如下:
class name = java.io.File
file name = ResourceTest_zh_CN.properties
file exists? = true
file absolute path = E:/project/designpattern/classes/ResourceTest_zh_CN.properties
======================================================
class name = java.io.File
file name = ResourceTest_zh_CN.properties
file exists? = true
file absolute path = E:/project/designpattern/classes/ResourceTest_zh_CN.properties
但是如果我把ResourceTest_zh_CN.properties剪切到resource目錄下,無論怎麼執行都報FileNotFoundException。看了一下ResourceUtils的源代碼:
Assert.notNull(resourceLocation, "Resource location must not be null");
if (resourceLocation.startsWith(CLASSPATH_URL_PREFIX)) {
String path = resourceLocation.substring(CLASSPATH_URL_PREFIX.length());
String description = "class path resource [" + path + "]";
URL url = ClassUtils.getDefaultClassLoader().getResource(path);
if (url == null) {
throw new FileNotFoundException(
description + " cannot be resolved to absolute file path " +
"because it does not reside in the file system");
}
return getFile(url, description);
}
try {
// try URL
return getFile(new URL(resourceLocation));
}
catch (MalformedURLException ex) {
// no URL -> treat as file path
return new File(resourceLocation);
}
}
從上可以看出ResourceUtils是通過ClassLoader的getResource方法來取得文件的。這兒岔開話題一下,可以注意到Class也有getResource和getResourceAsStream方法,這兩個有什麼區別呢?用代碼來說話吧,先看一下目錄圖如下:
代碼如下:
public static String FILE_NAME = "ResourceTest_zh_CN.properties";
public static String ABSOLUTE_PATH =
"E:/project/designpattern/classes/";
public static void main(String[] args) throws Exception {
System.out.println(ResourceTest.class.getClassLoader().getResource("com/learn/spring/test/resource/" + FILE_NAME));
System.out.println(ResourceTest.class.getClassLoader().getResourceAsStream("com/learn/spring/test/resource/" + FILE_NAME));
System.out.println(ResourceTest.class.getResource(FILE_NAME));
System.out.println(ResourceTest.class.getResourceAsStream(FILE_NAME));
}
}
這樣輸出結果正確,顯然ClassLoader和Class的兩個方法的區別一看便知,它們相對路徑不一樣,Class是把class文件所在的目錄做爲根目錄,ClassLoader是把加載所有classpath的目錄爲根目錄,也就是“..../classes”。
好,回到Spring的代碼,如果把ResourceTest_zh_CN.properties剪切到resource目錄下,而且要第一段代碼執行正確的話,我們可以這樣修改(上面的Class和ClassLoader的兩個方法的對比已經很清楚),更改代碼如下就可以了:
public static String FILE_NAME = "ResourceTest_zh_CN.properties";
public static String ABSOLUTE_PATH =
"E:/project/designpattern/classes/";
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
Resource resource = null;
resource = new ClassPathResource(FILE_NAME, ResourceTest.class);
print(resource);
resource = new FileSystemResource(ABSOLUTE_PATH + "com/learn/spring/test/resource/" + FILE_NAME);
print(resource);
File file = ResourceUtils.getFile("classpath:" + "com/learn/spring/test/resource/" + FILE_NAME);
print(file);
file = ResourceUtils.getFile("file:" + ABSOLUTE_PATH + "com/learn/spring/test/resource/" + FILE_NAME);
print(file);
}
public static void print(Resource resource) throws Exception {
System.out.println("======================================================");
System.out.println("class name = " + resource.getClass().getName());
System.out.println("file name = " + resource.getFilename());
System.out.println("file exists? = " + resource.exists());
System.out.println("file url = " + resource.getURL());
System.out.println("file description = " + resource.getDescription());
}
public static void print(File file) throws Exception {
System.out.println("======================================================");
System.out.println("class name = " + file.getClass().getName());
System.out.println("file name = " + file.getName());
System.out.println("file exists? = " + file.exists());
System.out.println("file absolute path = " + file.getAbsolutePath());
}
}