Java加载classpath文件的正确姿势

Java中有多种加载资源的方式:

this.getClass().getResource(resourceName)

除非以”/“开头,否则找this类同包的文件。

Thread.currentThread().getContextClassLoader().getResource(resourceName)

ClassLoader可以共享,创建的线程使用Thread.setContextClassLoader,可以相互加载对象的资源。

如果没有设置则是其父线程的类加载器。

ClassLoader.getSystemClassLoader().getResource(resourceName)

需要使用root开始的完整路径

 

代码示例

 

项目结构:

Java加载classpath文件的正确姿势_第1张图片

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目录。

Java加载classpath文件的正确姿势_第2张图片

输出
 

-----------------------------------------
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

Java加载classpath文件的正确姿势_第3张图片

运行

Java加载classpath文件的正确姿势_第4张图片

我们可以看到和idea中输出的一致,是因为资源相当于class文件的路径不变。

 

二、加载Maven的资源

maven项目资源放在:src/main/resources目录。

Java加载classpath文件的正确姿势_第5张图片
输出

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   

目标资源的样子

 

Java加载classpath文件的正确姿势_第6张图片

maven中的资源加载

  • this.getClass().getResource: 如果用root开始的路径如”/root-resource.txt“才生效。因为资源在target目录下的classes文件夹下。

  • Thread.currentThread().getContextClassLoader().getResource(resourceName): 不带'/'会生效。

  • ClassLoader.getSystemClassLoader().getResource(resourceName): 和上面一样,不带斜线才生效。

如何修改maven中的资源目录?

可以在pom.xml文件中定义 标签来覆盖默认的资源路径。

如下面配置我们将 java和resources目录定义为资源目录。


    .....
    
      
        src/main/java
      
      
        src/main/resources
      
    
    .....
    

 

英文原文:https://www.logicbig.com/how-to/java/different-ways-to-load-resources.html

如果觉得本文对你有帮助,欢迎点赞评论,欢迎关注我,我将努力创作更多更好的文章。

你可能感兴趣的:(翻译,Java基础)