zoukankan      html  css  js  c++  java
  • classloader.getresources() 介绍

    ◆普通情况下,我们都使用相对路径来获取资源,这种灵活性比較大.

    比方当前类为com/bbebfe/Test.class

    而图像资源比方sample.gif应该放置在com/bbebfe/sample.gif

    而假设这些图像资源放置在icons文件夹下,则应该是com/bbebfe/icons/sample.gif

    通过当前类文件的路径获取资源主要有例如以下几种方式:

    · 如果当前类为com.bbebfe.Test

    · 包所在的目录为bin

    String imageName = "icons/sample.gif"

    1, 通过Class.getResource()定位类路径下的资源(bin/com/bbebfe/icons/sample.gif)

    Class clazz = this.getClass();

    URL url = clazz.getResource(imageName);

    2,通过ClassLoader.getResource()定位包的根文件夹下的资源(bin/icons/sample.gif)

    Class clazz = this.getClass();

    URLClassLoader loader = (URLClassLoader)clazz.getClassLoader();

    URL url = loader.getResource(imageName);

    3, 通过ClassLoader.findResource()提供自己定制的方式定位资源

    URL url = loader.findResource(imageName);

     

    ◆那么这三种方法有那些差别, 我们应该在何时使用哪种方法呢?

    · Class.getResource() 方法

    该方法实际通过该ClassClass LoadergetResource()方法来获得资源, 在调用ClassLoadergetResource()方法之前, Class.getResource()方法会对资源名称做一定的处理,构建一个该资源的绝对名称(absolute name, 大意是:

           +假设资源名称以'/'('"u002f') 開始, 则资源的绝对名称是'/'以后的部分.

                  假设imageName"/icons/sample.gif", 则在这里会变成"icons/sample.gif"

           +否则对于其它情况, 绝对名称将是例如以下形式(给资源名称的前面加上modified_package_name/):
                  modified_package_name/resource_name (
    修正的包名称/资源名称)

    当中修正的包名称含义是将当前对象所在的包名称中的'.'('"u002e')替换为'/'

    假设ClassLoader.getResource()方法返回一个值为nullURL, Class.getResource()方法终于会将资源请求交给ClassLoader.getSystemResource(java.lang.String).

    · ClassLoader.getResource() 方法

    该对资源进行查找, 资源的名称是以'/'分隔的路径, 这种方法首先查找自己的父亲ClassLoader,由自己的父ClassLoader来查找资源(实际上, 假设父亲的父亲不是空, 则父亲仍会向上提交查找请求). 假设自己的父ClassLoadernull, 则查找Java虚拟机中内建的class loader, 并将资源请求提交给它们, 假设这些操作都失败了, ClassLoader会调用自己的findResource()方法来查找资源.

    · ClassLoader.findResource() 方法

    该方法在内部查找指定的资源, 假设你实现了自己的Class Loader,则应该重载这种方法以自己特定的方式来查找类文件和资源.

     

    ◆通过以上的总结, 我们能够看到三点.

    1, 不管是getResource(), 还是findResource(), 这些方法都仅仅是资源的定位方法, 终于都仅仅是返回一个URL, 仅仅是对资源的定位而已, 我们随后应通过自己的方法来读取这些资源. 而在ClassClassLoader中还定义的有getResourceAsStream方法, 该方法是getResource的增强版, 这里就不介绍了.

    2,假设须要以类为相对路径查找资源, 则应该调用Class.getResource()方法, 不要直接调用ClassLoader.getResource()方法. 另外, 除非是你自定义了ClassLoader并重载了findResource方法,否则也不要直接调用ClassLoader.findResource方法, 由于在Class.getResource()方法中会对资源名称作一定的处理, 这在上面介绍了, 以下举个实例:

           如果我的当前类在EclipseprojectDatabase, 类所在的包是com.bbebfe.test, icons文件夹放在bin/com/bbebfe/test/文件夹下, 我须要得到icons/sample.gif文件的URL, 则调用this.getClass().getResource()得到的URL:

          file:/E:/MyLife/MyProjects/Eclipse3.2/Database/bin/com/bbebfe/test/icons/disremove.gif

     

    3, 有时候我们希望某个jar库的图像资源在同一个icons下统一管理, 而不是为每一个包以下的Class建一个icons, 也就是说须要以库为相对路径来查找资源, 此时则应该调用ClassLoader.getResource()方法, 举个样例:

    ·某个project有例如以下的包结构:

           com.bbebfe.ui

           com.bbebfe.test

           com.bbebfe.database

    ·假设以类为相对路径, 则在每一个包下都必须建立一个icons文件夹, 并放置对应的资源文件. 例如以下:

           com.bbebfe.ui/icons/...

           com.bbebfe.test/icons/...

           com.bbebfe.database/icons/...

    ·而我们可能希望在根文件夹下放置一个icons文件夹, 把全部资源放置在这里管理, 这样还能够防止资源的反复. 就是例如以下形式

           com.bbebfe.ui

           com.bbebfe.test

           com.bbebfe.database

           icons/sample.gif ...

           则此时我们应该调用ClassLoader.getResource方法, 因为它没有对资源名称作处理, 也就是说没有将修正的包名加入到资源名称前, 所以它会在类所在的包的根下去查找资源.(执行java程序的语法是java com.bbebfe.ui.Test, 所以根文件夹com文件夹的上级文件夹).

     

    ◆最后, Java中对资源进行定位的方法有非常多种, Eclipse源码中还有例如以下一段定位文件资源的代码, 还没有时间研究, 以后再谈:

    ProtectionDomain domain = Main.class.getProtectionDomain();

    CodeSource source = null;

    URL result = null;

    if (domain != null)

    source = domain.getCodeSource();//获得code source

    if (source != null)

          result = source.getLocation();//获得URL

              

    String path = decode(result.getFile());//

    // normalize to not have leading / so we can check the form

    File file = new File(path);

    path = file.toString().replace('""', '/');

    // create a file URL (via File) to normalize the form (e.g., put

    // the leading / on if necessary)

    path = new File(path).toURL().getFile();

     

     

    刚才试了一下,发现假设类路径上有反复的资源,getResource()方法会返回类路径上碰到的第一个资源。 

    getResources()则会返回当前类载入器路径上的全部反复资源以及父类载入器上的全部反复资源。 

    比方,在tomcat/lib文件夹下放置一个zip文件,包括config/aaa.txt文件, 
    WEB-INF/lib文件夹下复制一份这个zip文件, 
    再在src文件夹下放上config/aaa.txt文件, 

    getResource("config/aaa.txt")
    返回结果是: 
    file:/D:/eclipse/workspace/demo/WebContent/WEB-INF/classes/config/aaa.txt 

    getResources("config/aaa.txt")
    返回结果是: 
    file:/D:/eclipse/workspace/demo/WebContent/WEB-INF/classes/config/aaa.txt 
    jar:file:/D:/apache-tomcat-6.0.16/lib/aaaaa.jar!/config/aaa.txt 
    jar:file:/D:/eclipse/workspace/demo/WebContent/WEB-INF/lib/bbbbb.jar!/config/aaa.txt 

  • 相关阅读:
    129. Sum Root to Leaf Numbers
    113. Path Sum II
    114. Flatten Binary Tree to Linked List
    112. Path Sum
    100. Same Tree
    300. Longest Increasing Subsequence
    72. Edit Distance
    自定义js标签库
    JS 实现Table相同行的单元格自动合并示例代码
    mysql 高版本only_full_group_by 错误
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/4095699.html
Copyright © 2011-2022 走看看