Class.getResource()与ClassLoader.getResource()的区别
Class.getResource()
是指AAA.class.getResource()
-
Class.getResource(String name):在当前class类的同一路径下查找资源
-
ClassLoader.getResource(String name):在根目录下查找该资源文件,即"/"或classpath目录
粗解
-
在当前项目目录下查找指定的文件,此方式只能加载当前项目classpath下的文件,用.表示当前目录,不能以/开头,会报错
1
2
3
4
|
// 方式1
URL url = ClassLoader.getSystemResource(".");
// 方式2
url = LoaderResourceTest.class.getClassLoader().getResource(".");
|
url会输出当前class文件所在的根目录,比如当前我输出的结果就是file:/Users/chuan/Documents/projects_code/java-project/demo/demo-core/target/classes/
-
以当前类所在的目录为基础,在当前目录查找并加载指定名称的资源文件,比如当前类LoaderResourceTest在项目的cc.kevinlu.demo.core.loader
包中,若是我们以LoaderResourceTest.class.getResource("LoaderT.class")
的方式加载一个文件,则首先会在cc.kevinlu.demo.core.loader
包中查找LoaderT.class文件,若查找不到则返回null,如果我们想要加载其他包中的文件,则可以使用"/"开头并加上文件在项目中的完整包路径,比如LoaderResourceTest.class.getResource("/cc/kevinlu/demo/core/gof/facade/FacadeTest.class")
1
2
3
4
5
|
// 获取当前类所在的包目录
url = LoaderResourceTest.class.getResource(".");
// 获取其他包内的文件
url = LoaderResourceTest.class.getResource("/cc/kevinlu/demo/core/gof/facade/FacadeTest.class");
|
这两条语句的输出:
1
2
3
|
file:/Users/chuan/Documents/projects_code/java-project/demo/demo-core/target/classes/cc/kevinlu/demo/core/loader/
file:/Users/chuan/Documents/projects_code/java-project/demo/demo-core/target/classes/cc/kevinlu/demo/core/gof/facade/FacadeTest.class
|
由此可以很明显的看出Class的getResource是获取当前类所在的包目录,如果不同的包中都有相同名称的资源文件,但是仅针对当前包可用,那么就可以使用这种方式去加载读取,不会出现读到其他目录的文件的情况,但是这仅受限于我们写的类,不适用于jar包中的。
-
如果我们想读取项目中引用的jar包内的文件,那么怎么办?其实和读取项目中自己写的文件是相同的办法,因为在系统启动的时候会将jar包中的文件加载到classpath目录下,所以读取方式一样的。
-
以上讲解的只是读取单个资源,那么要是想把所有匹配到的资源都获取到,则可以使用Class.getClassLoader().getResources()
和ClassLoader.getSystemResources()
两种方式
1
2
3
4
5
6
7
8
9
10
|
Enumeration<URL> urls = LoaderResourceTest.class.getClassLoader().getResources("META-INF/spring.factories");
while (urls.hasMoreElements()) {
System.out.println(urls.nextElement());
}
System.out.println("--ClassLoader.getSystemResources--");
urls = ClassLoader.getSystemResources("META-INF/spring.factories");
while (urls.hasMoreElements()) {
System.out.println(urls.nextElement());
}
|
-
读取资源文件内容方式
1
2
3
4
5
6
|
InputStream is = LoaderResourceTest.class.getClassLoader().getResourceAsStream("META-INF/spring.factories");
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String line = null;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
|
整个测试文件代码
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
|
package cc.kevinlu.demo.core.loader;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.Enumeration;
import org.springframework.boot.admin.SpringApplicationAdminMXBean;
public class LoaderResourceTest {
public static void main(String[] args) throws Exception {
// 在当前项目目录下查找指定的文件,此方式只能加载当前项目classpath下的文件,用.表示当前目录,不能以/开头,会报错
URL url = ClassLoader.getSystemResource(".");
System.out.println(url);
// 此方式和ClassLoader.getSystemResource一样
url = LoaderResourceTest.class.getClassLoader().getResource(".");
System.out.println(url);
// 以当前类所在的目录为基础,在当前目录查找并加载指定名称的资源文件,比如当前类LoaderResourceTest在
// 项目的cc.kevinlu.demo.core.loader包中,若是我们以LoaderResourceTest.class.getResource("LoaderT.class")的
// 方式加载一个文件,则首先会在cc.kevinlu.demo.core.loader包中查找LoaderT.class文件,若查找不到则返回null,如果我们想要加载其他包中的文件,
// 则可以使用/开头并加上文件在项目中的完整包路径,比如LoaderResourceTest.class.getResource("/cc/kevinlu/demo/core/gof/facade/FacadeTest.class")
url = LoaderResourceTest.class.getResource(".");
System.out.println(url);
url = LoaderResourceTest.class.getResource("/cc/kevinlu/demo/core/gof/facade/FacadeTest.class");
System.out.println(url);
// 获取jar包内的文件有以下方式
// 1. 使用Class.getClassLoader().getResource(),这种方式只能获取第一个匹配到的文件
System.out.println("************");
url = LoaderResourceTest.class.getClassLoader().getResource("META-INF/spring.factories");
System.out.println(url);
System.out.println("************");
// 2. 使用Class.getResource(),这种方式也只能获取第一个匹配到的文件
url = LoaderResourceTest.class.getResource("META-INF/spring.factories");
System.out.println(url);
// 3. 使用ClassLoader.getSystemResource()方法,这种也仅仅只是获取第一个匹配的文件
url = ClassLoader.getSystemResource("META-INF/spring.factories");
System.out.println(url);
// 那我们如果想要获取到所有匹配到的文件要怎么办呢?那么就使用Class.getClassLoader().getResources(),这个方法会返回一个Enumeration<URL>实例,
// 我们迭代返回的这个实例就可以读取所有匹配到的所有文件了,如果没有匹配到任何文件也可以大胆的去迭代,不用判空,因为在getResources方法中进行了非空封装
System.out.println("-----");
Enumeration<URL> urls = LoaderResourceTest.class.getClassLoader().getResources("META-INF/spring.factories");
while (urls.hasMoreElements()) {
System.out.println(urls.nextElement());
}
System.out.println("-----");
urls = ClassLoader.getSystemResources("META-INF/spring.factories");
while (urls.hasMoreElements()) {
System.out.println(urls.nextElement());
}
System.out.println("-----");
// 如果想要读取文件的具体内容,那么我们就要用到文件流了,常用的方法就是使用BufferedReader去读了
// getResourceAsStream()方法,它相当于你用getResource()取得File文件后,再new InputStream(file)一样的结果
InputStream is = LoaderResourceTest.class.getClassLoader().getResourceAsStream("META-INF/spring.factories");
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String line = null;
int i = 1;
while (i == 1 && (line = br.readLine()) != null) {
System.out.println(line);
i++;
}
System.out.println("*******");
url = SpringApplicationAdminMXBean.class.getResource(".");
System.out.println(url);
}
}
|