<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          面試官:Class和ClassLoader的getResource方法有啥區(qū)別?

          共 5038字,需瀏覽 11分鐘

           ·

          2022-01-16 23:06

          你知道的越多,不知道的就越多,業(yè)余的像一棵小草!

          你來(lái),我們一起精進(jìn)!你不來(lái),我和你的競(jìng)爭(zhēng)對(duì)手一起精進(jìn)!

          編輯:業(yè)余草

          cnblogs.com/54chensongxia

          推薦:https://www.xttblog.com/?p=5306

          最近在看寫Spring的源代碼,里面有好多地方都用到了Class和ClassLoader類的getResource方法來(lái)加載資源文件。之前對(duì)這兩個(gè)類的這個(gè)方法一知半解,概念也很模糊,這邊做下整理,加深理解。

          訪問(wèn)資源的主要方式

          在Java中,通??梢酝ㄟ^(guò)以下方式來(lái)訪問(wèn)資源:

          • Class的getResource方法;
          • ClassLoader的getResource方法;
          • ClassLoader的getResources方法; //獲取批量資源
          • ClassLoader的getSystemResource; //靜態(tài)方法

          在使用中,Class可通過(guò)直接引用類的class屬性而獲得,或是通過(guò)實(shí)例的 getClass() 方法來(lái)獲得。獲取ClassLoader的方式則比較多,常見以下幾種:

          • 調(diào)用Class的getClassLoader方法,如:getClass().getClassLoader()
          • 由當(dāng)前線程獲取ClassLoader:Thread.currentThread().getContextClassLoader()
          • 獲取系統(tǒng)ClassLoader: ClassLoader.getSystemClassLoader()

          Class.getResource 與 ClassLoader.getResource 的區(qū)別

          public?class?ClassLoaderAndClassContrast?{

          public?static?void?main(String[]?args)?throws?Exception?{
          ?Class?aClass?=?ClassLoaderAndClassContrast.class;
          ?ClassLoader?classLoader?=?aClass.getClassLoader();

          ?URL?resource?=?classLoader.getResource("cookies.properties");
          ?URL?resource1?=?aClass.getResource("dir/cookies.properties");
          ?if(resource!=null){
          ??byte[]?bytes?=?FileCopyUtils.copyToByteArray(resource.openStream());
          ?????System.out.println(new?String(bytes));
          ?}
          }
          }

          兩者最大的區(qū)別,是從哪里開始尋找資源。

          • ClassLoader并不關(guān)心當(dāng)前類的包名路徑,它永遠(yuǎn)以classpath為基點(diǎn)來(lái)定位資源。需要注意的是在用ClassLoader加載資源時(shí),路徑不要以"/"開頭,所有以"/"開頭的路徑都返回null;
          • Class.getResource如果資源名是絕對(duì)路徑(以"/"開頭),那么會(huì)以classpath為基準(zhǔn)路徑去加載資源,如果不以"/"開頭,那么以這個(gè)類的Class文件所在的路徑為基準(zhǔn)路徑去加載資源。

          在實(shí)際開發(fā)過(guò)程中建議使用Class.getResource這個(gè)方法,但是如果你想獲取批量資源,那么就必須使用到ClassLoader的getResources()方法。

          public?class?ClassLoaderAndClassContrast?{

          ????Class?cls?=?ClassLoaderAndClassContrast.class;
          ????ClassLoader?ldr?=?cls.getClassLoader();

          ????public?static?void?println(Object?s)?{
          ????????System.out.println(s);
          ????}

          ????void?showResource(String?name)?{
          ????????println("##?Test?resource?for:?“"?+?name?+?"”?##");
          ????????println(String.format("ClassLoader#getResource(\"%s\")=%s",?name,?ldr.getResource(name)));
          ????????println(String.format("Class#getResource(\"%s\")=%s",?name,?cls.getResource(name)));
          ????}

          ????public?final?void?testForResource()?throws?Exception?{
          ????????showResource("");
          ????????//對(duì)于Class來(lái),返回這個(gè)類所在的路徑
          ????????showResource("/");
          ????????showResource(cls.getSimpleName()?+?".class");
          ????????String?n?=?cls.getName().replace('.',?'/')?+?".class";
          ????????showResource(n);
          ????????showResource("/"?+?n);
          ????????showResource("java/lang/Object.class");
          ????????showResource("/java/lang/Object.class");
          ????}

          ????public?static?void?main(String[]?args)?throws?Exception?{
          ????????println("java.class.path:?"?+?System.getProperty("java.class.path"));
          ????????println("user.dir:?"?+?System.getProperty("user.dir"));
          ????????println("");
          ????????ClassLoaderAndClassContrast?t?=?new?ClassLoaderAndClassContrast();
          ????????t.testForResource();
          ????}
          }

          正確使用getResource方法

          • 避免使用 Class.getResource("/") 或 ClassLoader.getResource("")。你應(yīng)該傳入一個(gè)確切的資源名,然后對(duì)輸出結(jié)果作計(jì)算。比如,如果你確實(shí)想獲取當(dāng)前類是從哪個(gè)類路徑起點(diǎn)上執(zhí)行的,以前面提到的test.App來(lái)說(shuō),可以調(diào)用 App.class.getResource(App.class.getSimpleName() + ".class")。如果所得結(jié)果不是 jar 協(xié)議的URL,說(shuō)明 class 文件沒(méi)有打包,將所得結(jié)果去除尾部的 "test/App.class",即可獲得 test.App 的類路徑的起點(diǎn);如果結(jié)果是 jar 協(xié)議的 URL,去除尾部的 "!/test/App.class",和前面的 "jar:",即是 test.App 所在的 jar 文件的url。
          • 如果要定位與某個(gè)類同一個(gè)包的資源,盡量使用那個(gè)類的getResource方法并使用相對(duì)路徑。如前文所述,要獲取與 test.App.class 同一個(gè)包下的 App.js 文件,應(yīng)使用 App.class.getResource("App.js") 。當(dāng)然,事無(wú)絕對(duì),用 ClassLoader.getResource("test/App.js") 也可以,這取決于你所面對(duì)的問(wèn)題是什么。
          • 如果對(duì)ClassLoader不太了解,那就盡量使用Class的getResource方法。
          • 如果不理解或無(wú)法確定該傳給Class.getResource 方法的相對(duì)路徑,那就以類路徑的頂層包路徑為參考起點(diǎn),總是傳給它以 "/" 開頭的路徑吧。
          • 不要假設(shè)你的調(diào)試環(huán)境就是最后的運(yùn)行環(huán)境。你的代碼可能不打包,也可能打包,你得考慮這些情況,不要埋坑。

          獲取批量資源

          使用classLoader的getResources方法可以獲得批量資源

          ClassLoader?classLoader?=?Thread.currentThread().getContextClassLoader();
          Enumeration?resources?=?classLoader.getResources("META-INF/MANIFEST.MF");

          Spring的ResourceLoader

          在Spring框架中ResourceLoader和ResourcePatternResolver接口封裝了獲取資源的方法,我們可以直接拿來(lái)使用。ResourceUtils這個(gè)類中提供了很多判斷資源類型的工具方法,可以直接使用。

          //前面三種的寫法效果是一樣的,必須從classpath基準(zhǔn)目錄開始寫精確的匹配路徑
          //如果想匹配多個(gè)資源,需要以classpath*/打頭,然后配合通配符使用
          ClassPathXmlApplicationContext?applicationContext?=?new?ClassPathXmlApplicationContext("beans.spring.xml");

          ClassPathXmlApplicationContext?applicationContext?=?new?ClassPathXmlApplicationContext("/beans.spring.xml");

          ClassPathXmlApplicationContext?applicationContext?=?new?ClassPathXmlApplicationContext("classpath:/beans.spring.xml");

          ClassPathXmlApplicationContext?applicationContext?=?new?ClassPathXmlApplicationContext("classpath*:/**/beans.spring.xml");
          • ResourceLoader 接口
          • ResourcePatternResolver 接口 --- 重點(diǎn)

          給出一個(gè)例子

          String?txt?=?"";
          ResourcePatternResolver?resolver?=?new?PathMatchingResourcePatternResolver();
          Resource[]?resources?=?resolver.getResources("templates/layout/email.html");
          Resource?resource?=?resources[0];
          //獲得文件流,因?yàn)樵趈ar文件中,不能直接通過(guò)文件資源路徑拿到文件,但是可以在jar包中拿到文件流
          InputStream?stream?=?resource.getInputStream();
          StringBuilder?buffer?=?new?StringBuilder();
          byte[]?bytes?=?new?byte[1024];
          try?{
          ????for?(int?n;?(n?=?stream.read(bytes))?!=?-1;?)?{
          ????????buffer.append(new?String(bytes,?0,?n));
          ????}
          }?catch?(IOException?e)?{
          ????e.printStackTrace();
          }
          txt?=?buffer.toString();
          • ResourceUtils
          • ResourcePatternUtils

          瀏覽 45
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲综合成人在线视频 | 日韩一区三区 | 在线黄色小视频 | 伊人影院麻豆 | WWW.亚洲555久久久 |