Java中有多种加载资源的方式:
this.getClass().getResource(resourceName)
除非以”/“开头,否则找this类同包的文件。
Thread.currentThread().getContextClassLoader().getResource(resourceName)
ClassLoader可以共享,创建的线程使用Thread.setContextClassLoader,可以相互加载对象的资源。
如果没有设置则是其父线程的类加载器。
ClassLoader.getSystemClassLoader().getResource(resourceName)
需要使用root开始的完整路径
代码示例
项目结构:
package com.logicbig.example;
import java.io.IOException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
public class ClassA {
private static final String line = "-----------------------------------------";
private void loadResource (String resource) throws IOException {
URL u = this.getClass().getResource(resource);
loadResourceByUrl(u, resource);
}
private void loadResourceWithContextLoader (String resource) throws IOException {
URL u = Thread.currentThread().getContextClassLoader().getResource(resource);
loadResourceByUrl(u, resource);
}
private void loadResourceWithSystemClassLoader (String resource) throws IOException {
URL u = ClassLoader.getSystemClassLoader().getResource(resource);
loadResourceByUrl(u, resource);
}
private void loadResourceByUrl (URL u, String resource) throws IOException {
System.out.println("-> attempting input resource: "+resource);
if (u != null) {
String path = u.getPath();
path = path.replaceFirst("^/(.:/)", "$1");
System.out.println(" absolute resource path found :\n " + path);
String s = new String(Files.readAllBytes(Paths.get(path)));
System.out.println(" file content: "+s);
} else {
System.out.println(" no resource found: " + resource);
}
}
public static void main (String[] args) throws IOException {
ClassA a = new ClassA();
System.out.println(line+"\nusing this.getClass().getResource\n"+line);
a.loadResource("test-pkg-resource.txt");
a.loadResource("/test-pkg-resource.txt");
a.loadResource("root-resource.txt");
a.loadResource("/root-resource.txt");
System.out.println(line+"\n using current thread context loader\n"+line);
a.loadResourceWithContextLoader("test-pkg-resource.txt");
a.loadResourceWithContextLoader("/test-pkg-resource.txt");
a.loadResourceWithContextLoader("root-resource.txt");
a.loadResourceWithContextLoader("/root-resource.txt");
System.out.println(line+"\n using ClassLoader.getSystemClassLoader()\n"+line);
a.loadResourceWithSystemClassLoader("test-pkg-resource.txt");
a.loadResourceWithSystemClassLoader("/test-pkg-resource.txt");
a.loadResourceWithSystemClassLoader("root-resource.txt");
a.loadResourceWithSystemClassLoader("/root-resource.txt");
}
}
如果使用 IntelliJ IDE 15.0.2和JDK 1.8环境,资源将被拷贝到输出目录。资源在运行时将被拷贝到resources目录。
输出
-----------------------------------------
using this.getClass().getResource
-----------------------------------------
-> attempting input resource: test-pkg-resource.txt
absolute resource path found :
C:/load-resource/out/production/load-resource/com/logicbig/example/test-pkg-resource.txt
file content: test file, local to package
-> attempting input resource: /test-pkg-resource.txt
no resource found: /test-pkg-resource.txt
-> attempting input resource: root-resource.txt
no resource found: root-resource.txt
-> attempting input resource: /root-resource.txt
absolute resource path found :
C:/load-resource/out/production/load-resource/root-resource.txt
file content: root test file
-----------------------------------------
using current thread context loader
-----------------------------------------
-> attempting input resource: test-pkg-resource.txt
no resource found: test-pkg-resource.txt
-> attempting input resource: /test-pkg-resource.txt
no resource found: /test-pkg-resource.txt
-> attempting input resource: root-resource.txt
absolute resource path found :
C:/load-resource/out/production/load-resource/root-resource.txt
file content: root test file
-> attempting input resource: /root-resource.txt
no resource found: /root-resource.txt
-----------------------------------------
using ClassLoader.getSystemClassLoader()
-----------------------------------------
-> attempting input resource: test-pkg-resource.txt
no resource found: test-pkg-resource.txt
-> attempting input resource: /test-pkg-resource.txt
no resource found: /test-pkg-resource.txt
-> attempting input resource: root-resource.txt
absolute resource path found :
C:/load-resource/out/production/load-resource/root-resource.txt
file content: root test file
-> attempting input resource: /root-resource.txt
no resource found: /root-resource.txt
命令行运行
C:\load-resource>javac com/logicbig/example/ClassA.java
运行
我们可以看到和idea中输出的一致,是因为资源相当于class文件的路径不变。
maven项目资源放在:src/main/resources目录。
输出
C:\load-resource>mvn exec:java -Dexec.mainClass="com.logicbig.example.ClassA"
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building load-resource 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- exec-maven-plugin:1.4.0:java (default-cli) @ load-resource ---
-----------------------------------------
using this.getClass().getResource
-----------------------------------------
-> attempting input resource: test-pkg-resource.txt
no resource found: test-pkg-resource.txt
-> attempting input resource: /test-pkg-resource.txt
absolute resource path found :
C:/load-resource/target/classes/test-pkg-resource.txt
file content: test file, local to package
-> attempting input resource: root-resource.txt
no resource found: root-resource.txt
-> attempting input resource: /root-resource.txt
absolute resource path found :
C:/load-resource/target/classes/root-resource.txt
file content: root test file
-----------------------------------------
using current thread context loader
-----------------------------------------
-> attempting input resource: test-pkg-resource.txt
absolute resource path found :
C:/load-resource/target/classes/test-pkg-resource.txt
file content: test file, local to package
-> attempting input resource: /test-pkg-resource.txt
no resource found: /test-pkg-resource.txt
-> attempting input resource: root-resource.txt
absolute resource path found :
C:/load-resource/target/classes/root-resource.txt
file content: root test file
-> attempting input resource: /root-resource.txt
no resource found: /root-resource.txt
-----------------------------------------
using ClassLoader.getSystemClassLoader()
-----------------------------------------
-> attempting input resource: test-pkg-resource.txt
absolute resource path found :
C:/load-resource/target/classes/test-pkg-resource.txt
file content: test file, local to package
-> attempting input resource: /test-pkg-resource.txt
no resource found: /test-pkg-resource.txt
-> attempting input resource: root-resource.txt
absolute resource path found :
C:/load-resource/target/classes/root-resource.txt
file content: root test file
-> attempting input resource: /root-resource.txt
no resource found: /root-resource.txt
目标资源的样子
maven中的资源加载
/root-resource.txt
“才生效。因为资源在target目录下的classes文件夹下。
如何修改maven中的资源目录?
可以在pom.xml文件中定义 标签来覆盖默认的资源路径。
如下面配置我们将 java和resources目录定义为资源目录。
.....
src/main/java
src/main/resources
.....
英文原文:https://www.logicbig.com/how-to/java/different-ways-to-load-resources.htm