zoukankan      html  css  js  c++  java
  • 关于获取资源文件,Class.getResource和ClassLoader.getResource的区别

    原文同步发表至个人博客【夜月归途】

    原文链接:http://www.guitu18.com/post/2019/02/23/28.html

    在Java中经常会需要读取各种各样的配置文件,在获取资源时,一般会用到 Class.getResource()ClassLoader.getResource() ;

    那么这两种方式在获取资源文件时有什么相同或者不同的地方呢?

    先贴上代码目录结构:

    ┌─src
    │  └─main
    │     └─java
    │        └─com.guitu18.blog
    │           ├─classpath
    │           │  └─GetResourceTest.java
    │           └─SpringbootApplication.java
    └─resource
       ├─mapper
       │   └─BlogDao.xml
       └─confog.properties
    

    Class.getResource()

    测试代码,先看 this.getClass().getResource()
    代码的输出结果我直接贴在代码的上一行了,下同。

    @Test
    public void classGetResource() {
        // file:/E:/repo/guitu-blog/target/test-classes/com/guitu18/blog/classpath/
        System.out.println(this.getClass().getResource(""));
        // file:/E:/repo/guitu-blog/target/test-classes/
        System.out.println(this.getClass().getResource("/"));
    }
    

    可以看出,getResource("") 获取的是当前类所在包的路径,而 getResource("/") 获取的是 classpath 根路径;

    继续测试,我们获取目录下的文件:

    @Test
    public void classGetProperties() {
        // file:/E:/repo/guitu-blog/target/classes/config.properties
        System.out.println(this.getClass().getResource("/config.properties"));
        // null
        System.out.println(this.getClass().getResource("BlogDao.xml"));
        // file:/E:/repo/guitu-blog/target/classes/mapper/BlogDao.xml
        System.out.println(this.getClass().getResource("/mapper/BlogDao.xml"));
        /**
         * .java文件在编译后编程.class,所以这里参数传的文件名是.class结尾
         */
        // file:/E:/repo/guitu-blog/target/classes/com/guitu18/blog/classpath/GetResourceTest.class
        System.out.println(this.getClass().getResource("GetResourceTest.class"));
        // file:/E:/repo/guitu-blog/target/classes/com/guitu18/blog/SpringbootApplication.class
        System.out.println(this.getClass().getResource("../SpringbootApplication.class"));
        // file:/E:/repo/guitu-blog/target/classes/com/guitu18/blog/classpath/GetResourceTest.class
        System.out.println(this.getClass().getResource("../classpath/GetResourceTest.class"));
    }
    

    输出结果显示:

    1. 当以 "/" 开头时,是从 classpath 路径开始匹配资源;
    2. 当不以 "/" 开头时,是从当前类所在包的路径开始匹配资源;
    3. 两种方式都可以通过 "/""../" 在文件夹上下层路径切换;

    另外,在获取文件时,我们还可以通过 getResourceAsStream 直接获取文件输入流,如:

    InputStream inputStream = this.getClass().getResourceAsStream("/config.properties");
    

    getResourceAsStream()getResource() 在获取文件流和文件路径时,路径选择机制是一样的。

    ClassLoader.getResource()

    接着看 this.getClass().getClassLoader().getResource ,上代码:

    @Test
    public void classLoaderGetResource() {
        // file:/E:/repo/guitu-blog/target/test-classes/
        System.out.println(this.getClass().getClassLoader().getResource(""));
        // null
        System.out.println(this.getClass().getClassLoader().getResource("/"));
    }
    

    在使用 ClassLoader().getResource 获取路径时,不能以 "/" 开头,且路径总是从 classpath 根路径开始;

    @Test
    public void classLoaderGetProperties() {
        /**
         * 同样可以通过"/"或"../"在文件夹上下层路径切换
         */
        // file:/E:/repo/guitu-blog/target/classes/config.properties
        System.out.println(this.getClass().getClassLoader().getResource("config.properties"));
        // null
        System.out.println(this.getClass().getClassLoader().getResource("BlogDao.xml"));
        // file:/E:/repo/guitu-blog/target/classes/mapper/BlogDao.xml
        System.out.println(this.getClass().getClassLoader().getResource("mapper/BlogDao.xml"));
        /**
         * 同Class.getResourceAsStream()一样,我们还可以通过ClassLoader.getResourceAsStream()直接获取文件输入流
         * ClassLoader.getResourceAsStream()和ClassLoader.getResource()在获取文件流和文件路径时,路径选择机制也是一样的
         */
        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("config.properties");
    }
    

    这里跟上面差别不大,所以直接把结果写在代码注释中了, ClassLoader().getResource 只能从 classpath 开始获取资源,同样也能使用getResourceAsStream() 获取文件输入流,且路径机制一样;

    总结

    1. Class.getResource() 可以从当前 Class 所在包的路径开始匹配获取资源,也可以从 classpath 根路径开始匹配获取资源;
    2. ClassLoader().getResource() 只能从 classpath 根路径开始匹配获取资源;
    3. Class.getResource() 从当前包所在路径获取资源时不能以 "/" 开头,而从 classpath 根路径获取资源时必须以 "/" 开头;
    4. ClassLoader().getResource() 不能以 "/" 开头,且路径总是从 classpath 根路径开始;
    5. 它们都能通过 getResourceAsStream() 方法获取对应路径文件的输入流,文件路径匹配机制和其 getResource() 方法一样;
  • 相关阅读:
    MVC模式 与 Model2模型 介绍
    通过Servlet获取初始化参数
    《算法竞赛入门经典》学习笔记 2.3 文件操作
    《C++ Primer Plus》学习笔记 2.1.1 main()函数
    Codeforces Round #359 (Div. 2) C. Robbers' watch 搜索
    Github Pages建立个人博客
    《算法竞赛入门经典》第一章 程序设计入门 习题
    《C++ Primer Plus》学习笔记 第1章 预备知识
    在C#代码中应用Log4Net(一)简单使用Log4Net
    NHibernate实例
  • 原文地址:https://www.cnblogs.com/guitu18/p/10420459.html
Copyright © 2011-2022 走看看