1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        面試官: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)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            免费观看全黄做爰网站 | 北京女人操逼 | AV天堂偷拍亂伦 | 男人用嘴添女人下身视频 | 国产又色又爽又黄又免费 | 天天淫荡| 北条麻妃一区二区三区中文字幕 | 免费啪啪网站 | 少妇日批 | 影音先锋AV成人资源站在线播放 |