对各种读取资源文件的情况做了一下总结:
1. 场景说明
- 当前项目中,各个properties文件和java文件的相对位置,结构如下图所示:
- 在依赖的第三方jar包中,文件结构如下所示:
2. 代码
TestPath.java中读取取各个properties文件,主要采用以下两种方式:
方式一:Class.getResourceAsStream(path)
复制代码
和
方式二:Class.getClassLoader().getResourceAsStream(path)
复制代码
具体的测试代码如下:
/**
* Class.getResourceAsStream
*
* @param path
* 各个文件的路径
*/
public static void getResourceAsStream(String path) {
InputStream input = TestPath.class.getResourceAsStream(path);
showPath(input);
}
/**
* Class.ClassLoader.getResourceAsStream
*
* @param path
* 各个文件的路径
*/
public static void classLoadGetResourceAsStream(String path){
InputStream input = TestPath.class.getClassLoader().getResourceAsStream(path);
showPath(input);
}
/**
* print content in per file
* @param input
*/
public static void showPath(InputStream input) {
Properties prop = new Properties();
if (null == input) {
throw new RuntimeException("can not load properties: " + input);
}
try {
prop.load(input);
input.close();
for (Entry<Object, Object> entry : prop.entrySet()) {
System.out.println(entry.getKey().toString() + "="
+ entry.getValue().toString());
}
} catch (IOException e) {
throw new RuntimeException("can not read properties: " + input);
}
}
复制代码
3. 方式一
- 测试代码
public static void testGetResourceAsStream() {
System.out.println("文件与当前class在同一目录");
getResourceAsStream("current_path.properties");
getResourceAsStream("/com/java/path/test/current_path.properties");
System.out.println("文件在当前class上级目录");
getResourceAsStream("../parent_path.properties");
getResourceAsStream("/com/java/path/parent_path.properties");
System.out.println("文件与当前class在不同的package");
getResourceAsStream("/com/java/pathanother/another_package.properties");
System.out.println("文件在class根目录");
getResourceAsStream("/root_path.properties");
System.out.println("文件位于的依赖第三方包");
getResourceAsStream("/META-INF/maven/commons-logging/commons-logging/pom.properties");
}
复制代码
- 输出
文件与当前class在同一目录
path=com.java.path.test
path=com.java.path.test
文件在当前class上级目录
path=com.java.path
path=com.java.path
文件与当前class在不同的package
path=com.java.pathanother
文件在class根目录
path=root
文件位于的依赖第三方包
version=1.1.1
groupId=commons-logging
artifactId=commons-logging
复制代码
4. 方式二
- 测试代码
public static void testClassLoadGetResourceAsStream() {
System.out.println("文件与当前class在同一目录");
classLoadGetResourceAsStream("com/java/path/test/current_path.properties");
System.out.println("文件在当前class上级目录");
classLoadGetResourceAsStream("com/java/path/parent_path.properties");
System.out.println("文件与当前class在不同的package");
classLoadGetResourceAsStream("com/java/pathanother/another_package.properties");
System.out.println("文件在class根目录");
classLoadGetResourceAsStream("root_path.properties");
System.out.println("文件位于的依赖第三方包");
classLoadGetResourceAsStream("META-INF/maven/commons-logging/commons-logging/pom.properties");
}
复制代码
- 输出
文件与当前class在同一目录
path=com.java.path.test
文件在当前class上级目录
path=com.java.path
文件与当前class在不同的package
path=com.java.pathanother
文件在class根目录
path=root
文件位于的依赖第三方包
version=1.1.1
groupId=commons-logging
artifactId=commons-logging
复制代码
5. 总结
-
Test.class.getResource()
中资源可以写成绝对路径和相对路径 - 如果
Test.class.getResource()
资源是以/
开头,则指向CLASSPATH
根目录 - 如果
Test.class.getResource()
资源是以文件(包名)
开头,则相对Test.class
文件所在的包查找资源 -
Test.class.getClassLoader().getResource()
资源 只能写成相对路径,以文件(包名)
开头(注:getClassLoader().getResource("/")
是错误的),是以CLASSPATH
为根目录查找资源,相当于class.getResource()中写绝对路径。
6. 注意
- src/main/java
中的java文件
只能直接加载src/main/resources
下的资源,不能直接加载src/test/resources
下的资源; - src/test/java
中的java文件
既能加载src/test/resources
下的资源,又能加载src/main/resources
下的资源
当两个resources下都有要加载的同名资源时候,优先选择src/test/java
下的资源;