Java 中如何获取 classpath 下资源文件?

简介: Java 中的资源有多种,如File,URL, InputStream等,本篇将介绍在Java中获取classpath下的资源文件的几种方式

Java 中的资源有多种,如File,URL, InputStream等,本篇将介绍在Java中获取classpath下的资源文件的几种方式。

一 Class.getResource

String name1 = "/prop/system.properties";
URL url1 = App.class.getResource(name1);

二 Class.getResourceAsStream

String name1 = "/prop/system.properties";
InputStream inputStream1 = App.class.getResourceAsStream(name1);

三 ClassLoader.getResource

String name2 = "prop/system.properties";
 URL url2 = App.class.getClassLoader().getResource(name2);

四 ClassLoader.getResourceAsStream

String name2 = "prop/system.properties";
InputStream inputStream2 = App.class.getClassLoader().getResourceAsStream(name2);

五 ResourceBundle.getBundle

String name3 = "prop/system";
ResourceBundle resourceBundle = ResourceBundle.getBundle(name3);

注意资源名称不包含.properties


Class、ClassLoader获取资源文件区别

Class.getResource和Class.getResourceAsStream中,资源名称以"/"开头表示绝对定位,为类路径根目录下的资源文件, 否则资源名称被解析为以Class类的包名为父目录

ClassLoader.getResource和ClassLoader.getResourceAsStream中,资源名称不能以"/"开头,否则将找不到文件。

源码分析

Class类部分源码如下:

public final class Class<T> implements java.io.Serializable,GenericDeclaration,Type,AnnotatedElement {
    public java.net.URL getResource(String name) {
        name = resolveName(name);
        ClassLoader cl = getClassLoader0();
        if (cl==null) {
            // A system class.
            return ClassLoader.getSystemResource(name);
        }
        return cl.getResource(name);
    }
    public InputStream getResourceAsStream(String name) {
        name = resolveName(name);
        ClassLoader cl = getClassLoader0();
        if (cl==null) {
            // A system class.
            return ClassLoader.getSystemResourceAsStream(name);
        }
        return cl.getResourceAsStream(name);
    }
    private String resolveName(String name) {
        if (name == null) {
            return name;
        }
        if (!name.startsWith("/")) {
            Class<?> c = this;
            while (c.isArray()) {
                c = c.getComponentType();
            }
            String baseName = c.getName();
            int index = baseName.lastIndexOf('.');
            if (index != -1) {
                name = baseName.substring(0, index).replace('.', '/')
                    +"/"+name;
            }
        } else {
            name = name.substring(1);
        }
        return name;
    }
    ClassLoader getClassLoader0() { return classLoader; }
}


Class的getResource和getResourceAsStream首先调用resolveName方法解析资源名称,然后调用ClassLoader的getResource或getResourceAsStream方法;如果Class类中的域classLoader

为null还将调用ClassLoader.getSystemResource或ClassLoader.getSystemResourceAsStream方法获取系统资源。

Class的resolveName方法解析资源名称时对方法参数进行处理,如果以"/“开头则把开头的”/"截取,否则取包名为父目录和方法参数进行拼接。

ClassLoader部分源码如下:

public abstract class ClassLoader {
    public URL getResource(String name) {
        URL url;
        if (parent != null) {
            url = parent.getResource(name);
        } else {
            url = getBootstrapResource(name);
        }
        if (url == null) {
            url = findResource(name);
        }
        return url;
    }
    public InputStream getResourceAsStream(String name) {
        URL url = getResource(name);
        try {
            return url != null ? url.openStream() : null;
        } catch (IOException e) {
            return null;
        }
    }
}

ClassLoader的getResourceAsStream方法调用了getResource方法

ClassLoader的getResource方法首先尝试使用父类加载器获取资源,未获取到则调用findResource方法查找资源,findResource方法由子类覆盖。

总结

Class.getResource、 Class.getResourceAsStream、ClassLoader.getResourceAsStream最终都调用ClassLoader.getResource

如果将properties文件转换为java类Properties,可以使用ResourceBundle.getBundle方法。


目录
相关文章
|
2月前
|
Java 应用服务中间件 API
java 启动查看jar包加载顺序并设置classpath
java 启动查看jar包加载顺序并设置classpath
104 0
|
2月前
|
Java Maven
Class path contains multiple SLF4J bindings,后来找到的解决思路是idea2019.3必须用java11和idea2019.3版本,必须用applicatio
Class path contains multiple SLF4J bindings,后来找到的解决思路是idea2019.3必须用java11和idea2019.3版本,必须用applicatio
|
4月前
|
XML Java Maven
nested exception is java.io.FileNotFoundException: class path resource [springmvc.xml] cannot be ope
nested exception is java.io.FileNotFoundException: class path resource [springmvc.xml] cannot be ope
122 0
nested exception is java.io.FileNotFoundException: class path resource [springmvc.xml] cannot be ope
|
jenkins Java 持续交付
maven 打包项目报Fatal Error: Unable to find package java.lang in classpath or bootclasspat
maven 打包项目报Fatal Error: Unable to find package java.lang in classpath or bootclasspat
maven 打包项目报Fatal Error: Unable to find package java.lang in classpath or bootclasspat
|
4月前
|
IDE Java Unix
Java的class path的设置与应用
Java的class path的设置与应用
|
4月前
|
Java
如何解决使用若依前后端分离打包部署到服务器上后主包无法找到从包中的文件的问题?如何在 Java 代码中访问 jar 包中的资源文件?
如何解决使用若依前后端分离打包部署到服务器上后主包无法找到从包中的文件的问题?如何在 Java 代码中访问 jar 包中的资源文件?
382 0
|
12月前
|
Java 编译器
Java中环境变量 PATH 与 CLASSPATH 的区别
Java中环境变量 PATH 与 CLASSPATH 的区别
88 0
|
12月前
|
安全 Java Linux
JAVA环境变量JAVA_HOME、CLASSPATH、PATH设置详解
JAVA环境变量JAVA_HOME、CLASSPATH、PATH设置详解
57 0
|
消息中间件 Java RocketMQ
【Java】Error creating bean with name ‘functionBindingRegistrar‘ defined in class path resource的一种解决方式
【Java】Error creating bean with name ‘functionBindingRegistrar‘ defined in class path resource的一种解决方式
116 0
|
存储 前端开发 Java
【Java】If you want an embedded database (H2, HSQL or Derby), please put it on the classpath.
【Java】If you want an embedded database (H2, HSQL or Derby), please put it on the classpath.
187 0
下一篇
DDNS