`
扫地僧
  • 浏览: 29849 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

Java加载资源文件的方法

阅读更多

一、通过Class:getResource()加载资源

通过Class类的public java.net.URL getResource(String name)

public java.net.URL getResource(String name) {

        name = resolveName(name);

        ClassLoader cl = getClassLoader0();

        if (cl==null) {

            // A system class.

            return ClassLoader.getSystemResource(name);

        }

        returncl.getResource(name);

    }

通过Class类的getResource和通过ClassLoader的类加载资源的主要区别在于resolveName这个方法,我们来看下它的实现:

private String resolveName(String name) {

        if (name == null) {

            returnname;

        }

        if (!name.startsWith("/")) {

            Class<?> c = this;

            while (c.isArray()) {

                c = c.getComponentType();

            }

            String baseName = c.getName();

            intindex = baseName.lastIndexOf('.');

            if (index != -1) {

                name = baseName.substring(0, index).replace('.', '/')

                    +"/"+name;

            }

        } else {

            name = name.substring(1);

        }

        returnname;

    }

resolveName方法,如果是资源名是以/开头的绝对路径,例如/a/b/c,则返回a/b/cClassLoader调用;

如果资源名不是以/开头的绝对路径,例如a/b/c,则返回当前类grucee.test.Main的包路径grucee/test加上/+a/b/c,最后的结果就是grucee/test/a/b/c

我们来看两个示例:

资源文件如下图:



 
代码

publicstaticvoid main(String[] args) throws IOException {

       String absolutePath = "/test.properties";

       String relativePath = "test.properties";

      

       InputStream absoluteIn = Main.class.getResourceAsStream(absolutePath);

       InputStream relativeIn = Main.class.getResourceAsStream(relativePath);

      

       //假设编译后的文件按照包结构放置在bin目录(eclipse默认)

       //传绝对路径加载的是相对于bin目录的文件:bin/test.properties

       Properties absoluteProp = new Properties();

       absoluteProp.load(absoluteIn);

       System.out.println(absoluteProp.getProperty("path"));

      

       //传相对路径加载的是相对于Main.class所在目录的文件:bin/grucee/test/test.properties

       Properties relativeProp = new Properties();

       relativeProp.load(relativeIn);

       System.out.println(relativeProp.getProperty("path"));

    }

二、通过ClassLoader:getResource()加载资源

系统有哪些ClassLoader

1).Bootstrap Loader(引导类加载器):加载System.getProperty("sun.boot.class.path")所指定的路径或jar

2).Extended Loader(标准扩展类加载器ExtClassLoader):加载System.getProperty("java.ext.dirs")所指定的路径或jar。在使用Java运行程序时,也可以指定其搜索路径,例如:java -Djava.ext.dirs=d:\projects\testproj\classes HelloWorld

3).AppClass Loader(系统类加载器AppClassLoader):加载System.getProperty("java.class.path")所指定的路径或jar。在使用Java运行程序时,也可以加上-cp来覆盖原有的Classpath设置,例如: java -cp ./lavasoft/classes HelloWorld

4).自定义类加载器

ExtClassLoaderAppClassLoaderJVM启动后,会在JVM中保存一份,并且在程序运行中无法改变其搜索路径。如果想在运行时从其他搜索路径加载类,就要产生新的类加载器。

线程上下文类加载器

线程上下文类加载器(context class loader)是从 JDK 1.2 开始引入的。类 java.lang.Thread中的方法 getContextClassLoader()setContextClassLoader(ClassLoader cl)用来获取和设置线程的上下文类加载器。如果没有通过 setContextClassLoader(ClassLoader cl)方法进行设置的话,线程将继承其父线程的上下文类加载器。Java 应用运行的初始线程的上下文类加载器是系统类加载器。在线程中运行的代码可以通过此类加载器来加载类和资源。

前面提到的类加载器的代理模式并不能解决 Java 应用开发中会遇到的类加载器的全部问题。Java 提供了很多服务提供者接口(Service Provider InterfaceSPI),允许第三方为这些接口提供实现。常见的 SPI JDBCJCEJNDIJAXP JBI 等。这些 SPI 的接口由 Java 核心库来提供,如 JAXP SPI 接口定义包含在 javax.xml.parsers包中。这些 SPI 的实现代码很可能是作为 Java 应用所依赖的 jar 包被包含进来,可以通过类路径(CLASSPATH)来找到,如实现了 JAXP SPI  Apache Xerces所包含的 jar 包。SPI 接口中的代码经常需要加载具体的实现类。如 JAXP 中的 javax.xml.parsers.DocumentBuilderFactory类中的 newInstance()方法用来生成一个新的 DocumentBuilderFactory的实例。这里的实例的真正的类是继承自 javax.xml.parsers.DocumentBuilderFactory,由 SPI 的实现所提供的。如在 Apache Xerces 中,实现的类是 org.apache.xerces.jaxp.DocumentBuilderFactoryImpl。而问题在于,SPI 的接口是 Java 核心库的一部分,是由引导类加载器来加载的;SPI 实现的 Java 类一般是由系统类加载器来加载的。引导类加载器是无法找到 SPI 的实现类的,因为它只加载 Java 的核心库。它也不能代理给系统类加载器,因为它是系统类加载器的祖先类加载器。也就是说,类加载器的代理模式无法解决这个问题。

线程上下文类加载器正好解决了这个问题。如果不做任何的设置,Java 应用的线程的上下文类加载器默认就是系统上下文类加载器。在 SPI 接口的代码中使用线程上下文类加载器,就可以成功的加载到 SPI 实现的类。线程上下文类加载器在很多 SPI 的实现中都会用到。

加载资源的流程

ClassLoader加载配置文件时,路径均不能以"/"开头,在查找时直接在classpath下进行查找。

查看源代码:

public URL getResource(String name) {

        URL url;

        if (parent != null) {

            url = parent.getResource(name);

        } else {

            url = getBootstrapResource(name);

        }

        if (url == null) {

            url = findResource(name);

        }

        returnurl;

    }

假设我们没有自定义类加载器,并且我们调用的是系统类加载器的getResource,那么该ClassLoader就是AppClassLoader的实例,并且通过上述方法,依次会调用:

AppClassLoader:getResource->ExtClassLoader:getResource->getBootstrapResource()。也就是分别在加载启动类、扩展类、系统类的路径下寻找资源文件,和类加载采用相同的双亲委派机制。

并不是所有的类加载都符合双亲委派机制,因此类中加载的资源文件也不是都符合双亲委派机制。所以加载资源的时候,也需要用到线程上下文类加载器。我们通常使用下面的代码加载资源文件(通常使用ClassLoadergetResource(),它和类加载思路一致,因此更好理解):

privatestatic InputStream loadConfigFile() {

       //先使用当前类的类加载器查找资源

       InputStream in = FileLogReader.class.getClassLoader().getResourceAsStream(LoggerConstants.FILE_LOG_PATH);

       if (in == null) {

           //查找不到资源时,使用线程上下文的类加载器查找资源

           in = Thread.currentThread().getContextClassLoader()

                  .getResourceAsStream(LoggerConstants.FILE_LOG_PATH);

       }

       returnin;

    }

 

  • 大小: 6.8 KB
分享到:
评论

相关推荐

    Java加载properties文件的六种方法

    这种方法适用于全局的系统资源,从系统的类路径中加载 `.properties` 文件。示例: ```java InputStream in = ClassLoader.getSystemResourceAsStream(name); Properties p = new Properties(); p.load(in); `...

    Java加载配置文件工具类

    这个"Java加载配置文件工具类"很可能是为了解决这个问题而创建的一个实用工具,帮助开发者更方便、高效地处理配置文件。配置文件通常以.properties或.xml格式存在,用于存储应用程序的参数、配置项等。 配置文件的...

    java 静态代码块通过类加载器获取资源文件例子

    总之,通过Java的静态代码块和类加载器,我们可以有效地管理和加载资源文件,特别是属性配置文件,确保在程序启动时即完成初始化工作,提升应用性能。这种技术在大型复杂系统中尤其常见,因为它能够保证配置的正确性...

    java 读取资源文件

    // 加载资源文件 props.load(inputStream); // 访问属性 String propertyValue = props.getProperty("key"); System.out.println("Property value: " + propertyValue); } catch (Exception e) { e....

    Java 加载配置文件的方式

    以上就是Java中加载配置文件的一些常见方法,每种方法都有其适用的场景和优缺点。选择哪种方式取决于你的项目需求,如配置文件的位置、格式以及是否需要进行国际化处理等因素。在实际开发中,应根据具体情况灵活选择...

    Java 自动加载JAR文件并运行其中的类方法

    在Java编程中,有时我们需要动态地加载外部JAR文件,并执行其中特定的类方法,这在插件系统、模块化应用或动态扩展性需求中尤为常见。本篇将详细讲解如何实现这一目标。 首先,理解JAR(Java Archive)文件是Java...

    java文件的加载

    在Java应用开发中,特别是Web应用程序的构建过程中,资源文件(如配置文件、属性文件等)的加载是必不可少的一部分。本文将重点探讨Java环境下不同方式下的文件加载方法,尤其关注在Spring框架下的实践与应用。 ###...

    java读取文件方法大全

    ### Java读取文件方法大全:读取File流等技术 在Java中,读取文件是一项基本且重要的操作,它可以通过多种方式实现,如字节流、字符流和基于行的读取。下面将详细介绍这些方法: #### 字节级读取:`...

    java解析资源文件

    在Java编程中,解析资源文件是一项常见的任务,它涉及到读取和操作项目中的文本、配置、图片等非代码数据。本教程将深入讲解如何在Java中处理资源文件,以及使用jbom解析工具的相关知识。 首先,理解资源文件的定位...

    java热加载Class文件

    Java热加载Class文件是开发者在调试和优化代码时非常实用的一种技术,它允许开发者在不重启JVM的情况下更新和替换已加载的类,极大地提高了开发效率。本文将深入探讨Java热加载Class文件的相关知识点。 首先,理解...

    java加载obj,stl模型资源,html页面展示

    2. **Java加载3D模型**: - 在Java中,我们可以使用各种库来解析和加载这些3D模型,如J3D(Java 3D)、JMonkeyEngine或j3mdk等。这些库提供了API,可以读取OBJ和STL文件,并将数据转化为Java对象,以便进一步处理。...

    加载资源文件的PDF

    在Android开发中,加载资源文件,尤其是PDF文档,是一个常见的需求。这个"加载资源文件的PDF"项目提供了一个完美的示例,演示了如何在Android应用中实现PDF的加载、缩放以及保持清晰度。以下是对这个项目的详细解析...

    Jar包中如何正确地加载资源文件博文中用到的测试项目源码

    本篇文章将详细探讨如何在Java中正确地从JAR包中加载资源文件,并提供相应的源码示例。 首先,理解Java类路径(classpath)是关键。类路径是指Java虚拟机(JVM)查找.class文件和其他资源文件的路径。当你运行一个...

    加载文件资源的三种方式

    加载文件资源的三种方式 ~1.从classpath根目录下加载指定名称的文件 2.从classpath根目录下加载指定名称的文件 3. 从classpath根目录下加载指定名称的文件 4. 获取当前文件的绝对路径

    Java工程中资源文件的用法

    读取资源文件的过程包括将资源文件读入到输入流中,然后利用`Properties`类的`load()`方法加载到内存。具体步骤如下: 1. **创建Properties实例**:首先,创建一个`Properties`对象实例,这将用于存储从资源文件中...

    解决java打包之后无法加载静态资源的问题SWTResourceManager.java源码

    利用swt中的一个获取图片的类SwingResourceManager 来解决将程序打为使用java打包之后,生成的jar包中图片找不着的。这是因为通过class.getResource()方法在IDEA中运行的路径和生成jar包获取的的路径是不同的。打成...

    Java加载properties文件实现方式详解

    Java加载properties文件实现方式详解 Java加载properties文件是Java开发中常见的场景,properties文件是一种配置文件,用于存储应用程序的配置信息。Java提供了多种方式来加载properties文件,本文将详细介绍Java...

    java资源文件的处理

    System.err.println("无法加载资源文件: " + e.getMessage()); } ``` 4. **国际化(i18n)**: `.properties`文件也常用于实现应用程序的国际化。每个语言版本都有一个相应的资源文件,例如`messages_en....

    深入解析Java资源文件(Resource Bundle)的加载机制

    本文将详细介绍Java中资源文件的基本概念、加载机制以及如何使用Resource Bundle进行国际化和本地化。 Java中的资源文件(Resource Bundle)是实现国际化和本地化的强有力工具。通过本文的介绍,读者应该能够了解...

    Java加载资源文件的两种方法

    处理配置文件对于Java程序员来说再常见不过了,不管是Servlet,Spring,抑或是Structs,都...  在了解了Java加载资源文件的机制后,以上这两个问题便迎刃而解了。  对于第一个问题,答案是:请将你的资源文件放在c

Global site tag (gtag.js) - Google Analytics