getSystemResourceAsStream() 返回 null

10

你好... 我想使用getSystemResourceAsStream()方法将属性文件的内容读取到InputStream类对象中。我已经编写了示例代码,并且在main()方法中运行良好,但是当我部署项目并在服务器上运行时,无法获取属性文件路径...因此inputstream对象存储null值。

示例代码如下:

public class ReadPropertyFromFile {

    public static Logger logger = Logger.getLogger(ReadPropertyFromFile.class);

    public static String readProperty(String fileName, String propertyName) {
        String value = null;
        try {
            //fileName = "api.properties";
            //propertyName = "api_loginid";

            System.out.println("11111111...In the read proprty file.....");


            //  ClassLoader loader = ClassLoader.getSystemClassLoader();

            InputStream inStream = ClassLoader.getSystemResourceAsStream(fileName);

            System.out.println("In the read proprty file.....");
            System.out.println("File Name :" + fileName);
            System.out.println("instream = "+inStream);

            Properties prop = new Properties();

            try {
                prop.load(inStream);
                value = prop.getProperty(propertyName);
            } catch (Exception e) {
                logger.warn("Error occured while reading property " + propertyName + " = ", e);
                return null;
            }
        } catch (Exception e) {
            System.out.println("Exception = " + e);
        }
        return value;
    }

    public static void main(String args[]) {

      System.out.println("prop value = " + ReadPropertyFromFile.readProperty("api.properties", "api_loginid"));
   }
}

3
为什么使用系统类加载器而不是普通的类加载器? - skaffman
注意:自Java9+起,系统类加载器(又名应用程序类加载器)是“正常”的类加载器,即引导类加载器的孙子和平台类加载器的子代,请参见https://dev59.com/9FYO5IYBdhLWcg3wBdB5上的已接受答案。 - 8bitjunkie
3个回答

17

我部署了项目并在服务器上运行,

这听起来像是一个JSP/Servlet网站应用程序。在这种情况下,您需要使用以下方式获取的 ClassLoader:

ClassLoader classLoader = Thread.currentThread().getContextClassLoader();

这种方式可以访问与Web应用程序相关联的所有类路径路径,您不再依赖于加载类的父类加载器(Web应用程序有多个!)。

然后,在此类加载器上,您只需调用getResourceAsStream()方法以获取作为流的类路径资源,而不是getSystemResourceAsStream()。后者取决于Web应用程序的启动方式,您也不希望依赖它,因为您无法控制外部托管。

InputStream input = classLoader.getResourceAsStream("filename.extension");

这比你最初的getSystemResourceAsStream()方法和其他人建议的Class#getResourceAsStream()方法更稳健。


7

SystemClassLoader是从java.class.path加载资源的,该路径映射到系统变量CLASSPATH。在您的本地应用程序中,您可能已经将要加载的资源配置在java.class.path变量中。但在服务器上,情况就不同了,因为很可能服务器会从另一个类加载器加载您的资源。

尝试使用正确路径加载类的ClassLoader

getClass().getResourceAsStream(fileName);

这篇文章也许会有所帮助。


getClass().getResourceAsStream("input.properties"); 对我很有效。资源位于使用它的类的同一目录中。 - Salvatore Pannozzo Capodiferro

0

尝试使用getResourceAsStream()而不是getSystemResourceAsStream()


  1. 注意不要直接在Class类上调用Class.getResourceAsStream(name)方法 - 它会将name与调用它的类实例的包路径拼接起来。
  2. 调用this.getClass().getClassLoader().getResourceAsStream(name)ClassLoader.getSystemResourceAsStream(name)几乎是等效的。它们都从系统类加载器开始,通过ClassLoader.getResource(name)进行递归委派解析,然后在最后尝试使用系统类加载器查找资源,这样几乎总能找到你的资源。
- 8bitjunkie
我在上面的注释中说“几乎总是等同”,因为this.getClass().getClassLoader()高度可能会返回jdk.internal.loader.ClassLoaders$AppClassLoader(系统类加载器)的一个实例。 - 8bitjunkie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接