成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久

您的位置:首頁技術文章
文章詳情頁

Java 正確地從類路徑中獲取資源

瀏覽:180日期:2022-08-12 10:56:34
目錄Java 可通過以下幾種方法來訪問資源:Class.getResource 與 ClassLoader.getResource 的區別測試代碼打包為 Jar 包后的變化錯誤與陷阱正確使用 getResource 方法getResources: 枚舉資源實例Java 可通過以下幾種方法來訪問資源: Class 的 getResource 方法 ClassLoader 的 getResource 方法 ClassLoader 的 getSystemResource 靜態方法

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

調用 Class 的 getClassLoader 方法,如:getClass().getClassLoader() 由當前線程獲取 ClassLoader:Thread.currentThread().getContextClassLoader() 獲取系統 ClassLoader: ClassLoader.getSystemClassLoader()

不過,若是對 Java 的 ClassLoader 概念不太了解,最好還是盡量避免使用它。

Class.getResource 與 ClassLoader.getResource 的區別

這兩種方式,都接受一個字符串形式的路徑表達式,即資源名,并返回找到的資源的 URL。兩種方式都可用來定位資源,在網絡上流傳的文章中,兩者都是常見的。實際上,Class 的 getResource 方法也調用了 ClassLoader 的 getResource 方法,但兩者有著很大的不同,不了解這兩種方法的區別,就容易造成隱患。隱患經常比編寫時就出錯要可怕得多,因為它在一定場合下是正常的,不容易被發現。

兩者最大的區別,是從哪里開始尋找資源。ClassLoader 并不關心當前類的包名路徑,它永遠以 classpath 為基點來定位資源。而 Class.getResource 則不同,如果資源名是絕對路徑(以'/'開頭),它會將開頭的'/'去除,然后調用 ClassLoader 的 getResource 方法來尋找資源;如果資源名是相對路徑,它會在當前的包路徑下面尋找資源。

舉例來說,假設我們有一個類:test.App (包名為 test),并且在 test 包下有一個與類名同名的 js 文件,名為 App.js。如果用 ClassLoader 來獲取這個 js 文件,應該這樣寫:

App.class.getClassLoader().getResource('test/App.js');

如果用 Class 的 getResource 方法,則有兩種寫法:

使用相對路徑:

App.class.getResource('App.js'); 使用絕對路徑:

App.class.getResource('/test/App.js');

從上面的例子,可以看出兩者之間巨大的區別。有些人從網絡上復制類似的代碼,看看不能正確運行,就開始嘗試在資源名前加上 '/',或是去掉開頭的 '/',試成功了,便算完工,這絕非正道。

Class 與 ClassLoader 的 getResource 方法還有其它一些不同,對 Class 的 getResource 方法來說,若傳入的是相對路徑,它還會嘗試做包名與路徑名的轉換。查看 Class.getResource 方法的源碼,可以看到它首先對資源名調用了 resolveName 方法,然后再調用 ClassLoader 的 getResource 方法來完成資源的定位。

測試代碼

作為演示,我寫了以下代碼來展示 Class 與 ClassLoader 的 getResource 方法的輸出:

/** * Copyright (c) 2014 Chen Zhiqiang <chenzhiqiang@mail.com>. Released under the MIT license. */package test;import java.net.URL;import java.util.Enumeration;/** * Tests for the use of {@link Class#getResource(String)} and * {@link ClassLoader#getResource(String)}. * * @author Chen Zhiqiang <chenzhiqiang@mail.com> */public class ClassResourceTest { Class<ClassResourceTest> cls = ClassResourceTest.class; ClassLoader ldr = cls.getClassLoader(); // Thread.currentThread().getContextClassLoader() 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('');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('');ClassResourceTest t = new ClassResourceTest();t.testForResource(); }}

編譯上述代碼,看看不同資源路徑的輸出結果。

打包為 Jar 包后的變化

現在,將上述代碼編譯后的結果打包成 Jar 文件,假設是 test.jar ,然后從這個 jar 包中運行上述代碼,再看看輸出結果,比較下與上面的輸出有什么變化:

java -classpath test.jar test.ClassResourceTest

值得注意的幾點:

Class.getResource('') 還有其它一些輸出,結果是 jar:file:/some_path/test.jar!/some_path,而在打包為 Jar 之前,它們的輸出形式是 file:/some_path...; Class.getResource('/') 為 null,而在打包之前,該輸出是 ClassResourceTest 的類路徑; ClassLoader.getResource('') 為 null,而在打包之前,該輸出是 ClassResourceTest 的類路徑; 調用 ClassLoader.getResource 方法時,若資源名為絕對路徑,不管是否打包,其輸出結果為 null,至少在我這里是這樣。 錯誤與陷阱 使用 Class.getResource('/') 或 ClassLoader.getResource('') 來當作類路徑的根。

這是一種常見的錯誤,并在網絡上廣為流傳。它們在打包成 Jar 包后,其結果會發生變化。

獲得 getResource 方法的輸出后,簡單地對結果調用 getFile 或 getPath,并把它當作文件路徑來處理。

資源有可能以文件和目錄的形式位于類路徑之中,但也可能打包進了 Jar 包或 Zip 包,你不能假設你的代碼不會被打包。

將絕對路徑傳給 ClassLoader 的 getResource 方法。

網絡上有人說,對于 ClassLoader 的 getResource 方法來說,資源名是否以 '/' 開頭是一樣的,然而,在我這里,ClassLoader 的 getResource 方法并不接受絕對路徑,其輸出結果為 null。

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

Java 的 CLASSPATH 是一個路徑列表,因此,有可能在多個類路徑中出現同樣的資源名。如果要列舉它們,可以使用 ClassLoader 的 getResources 方法。

下面的代碼可以枚舉所有的 'META-INF/MANIFEST.MF',你還可以觀察到在類路徑中哪些 jar 文件包含有該資源:

import java.net.URL;import java.util.Enumeration;public class Test { public static void main(String[] args) throws Exception {ClassLoader ldr = Test.class.getClassLoader();System.out.println('## Test for getResources(‘META-INF/MANIFEST.MF’) ##');Enumeration<URL> urls = ldr.getResources('META-INF/MANIFEST.MF');while(urls.hasMoreElements()) System.out.println(urls.nextElement()); }}實例

下面的代碼演示了如何正確獲取代碼的類路徑起點:

/** * Copyright (c) 2014 Chen Zhiqiang <chenzhiqiang@mail.com>. Released under the MIT license. */package test;import java.io.File;import java.net.MalformedURLException;import java.net.URL;import java.util.regex.Matcher;import java.util.regex.Pattern;/** * 演示如何獲取當前類路徑的起點 * * @author Chen Zhiqiang <chenzhiqiang@mail.com> */public class AppDirTest {Classcls = AppDirTest.class;URL codeLocation = getCodeLocation();/** * Get the code location. * * Return the classpath where the code run from. The return url will be: * file:/path/my-app/calsses/ or file:/path/my-app/my-app.jar * * @return URL */public URL getCodeLocation() {if (codeLocation != null)return codeLocation;// Get code location using the CodeSourcecodeLocation = cls.getProtectionDomain().getCodeSource().getLocation();if (codeLocation != null)return codeLocation;// If CodeSource didn’t work, use {@link } Class.getResource instead.URL r = cls.getResource('');synchronized (r) {String s = r.toString();Pattern jar_re = Pattern.compile('jar:s?(.*)!/.*');Matcher m = jar_re.matcher(s);if (m.find()) { // the code is run from a jar file.s = m.group(1);} else {String p = cls.getPackage().getName().replace(’.’, ’/’);s = s.substring(0, s.lastIndexOf(p));}try {codeLocation = new URL(s);} catch (MalformedURLException e) {throw new RuntimeException(e);}}return codeLocation;}/** * Get the class path root where the program startup, if run in a jar, * return the jar file’s parent path. * * @return */public String getAppDir() {File f = new File(getCodeLocation().getPath());return f.isFile() ? f.getParent() : f.getPath();}public static void main(String[] args) {AppDirTest t = new AppDirTest();System.out.println('code location: ' + t.getCodeLocation());System.out.println('app dir: ' + t.getAppDir());}}

以上就是Java 正確地從類路徑中獲取資源的詳細內容,更多關于Java 從類路徑中獲取資源的資料請關注好吧啦網其它相關文章!

標簽: Java
相關文章:
成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久
首页亚洲欧美制服丝腿| 日韩欧美自拍偷拍| 欧美成va人片在线观看| 久久se精品一区精品二区| 久久久久久一区二区| 亚洲精品菠萝久久久久久久| 怡红院精品视频在线观看极品| 欧美高清在线精品一区| av电影在线观看一区| 欧美人xxxx| 经典三级在线一区| 欧美亚洲国产一区二区三区| 男女性色大片免费观看一区二区| 欧美艳星brazzers| 激情久久久久久久久久久久久久久久| 在线观看视频一区二区欧美日韩| 秋霞午夜av一区二区三区| 久久日韩精品| 日韩黄色在线观看| 欧美日韩中文字幕一区| 九色porny丨国产精品| 91久久精品日日躁夜夜躁欧美| 亚洲18色成人| 玖玖在线精品| 视频精品一区二区| 91久久国产综合久久| 久久99国产精品尤物| 69久久夜色精品国产69蝌蚪网| 国产麻豆精品在线观看| 欧美一二三在线| www.亚洲色图| 国产精品人成在线观看免费 | 久久精品国产色蜜蜜麻豆| 欧美在线制服丝袜| 国产精品12区| 国产欧美日本一区二区三区| 最新成人av网站| 亚洲午夜电影在线| 色噜噜狠狠一区二区三区果冻| 久久精品国产99国产| 日韩欧美国产一区在线观看| 欧美.日韩.国产.一区.二区| 亚洲男人的天堂在线观看| 奶水喷射视频一区| 久久99热这里只有精品| 91精品国产福利| 91麻豆国产精品久久| 一区二区三区在线影院| 欧美无砖砖区免费| 91在线精品一区二区| 国产精品精品国产色婷婷| 亚洲一区二区三区高清不卡| 五月天激情综合| 欧美日韩视频第一区| 粗大黑人巨茎大战欧美成人| 日本一区二区三区四区| 国产日韩精品久久| 六月丁香综合在线视频| 日韩精品中文字幕一区 | 全部av―极品视觉盛宴亚洲| 欧美顶级少妇做爰| 91碰在线视频| 亚洲男人的天堂网| 欧美日韩亚洲综合一区| 99精品视频在线免费观看| 国产精品成人在线观看 | 国产丝袜在线精品| 中文亚洲免费| 美女www一区二区| 精品日韩一区二区三区免费视频| 一区在线免费| 日本欧美一区二区三区乱码| 欧美二区在线观看| 欧美少妇一区| 日韩成人一区二区| 久久久久久一级片| 亚洲欧美精品在线观看| 国产麻豆精品视频| 国产精品欧美一区喷水| 麻豆九一精品爱看视频在线观看免费| 狠狠久久亚洲欧美| 亚洲欧美在线aaa| 欧美在线免费观看亚洲| 9色porny自拍视频一区二区| 亚洲一区二区美女| 精品少妇一区二区三区视频免付费| 在线成人h网| 激情五月播播久久久精品| 国产精品天美传媒| 欧美影视一区在线| 欧美特黄一级| 精品一区二区三区av| 国产精品毛片久久久久久久| 欧美午夜不卡在线观看免费| 欧美在线不卡| 乱一区二区av| 亚洲欧美一区二区久久| 91精品欧美综合在线观看最新| 亚洲欧洲视频| 国产精品一区一区| 亚洲视频每日更新| 666欧美在线视频| 妖精视频成人观看www| 成人免费看的视频| 午夜欧美一区二区三区在线播放| 久久蜜桃av一区精品变态类天堂| 久久久青草婷婷精品综合日韩 | 一本一道波多野结衣一区二区| www.一区二区| 蜜臀av性久久久久蜜臀av麻豆 | 国产一区免费电影| 亚洲精品va在线观看| 精品黑人一区二区三区久久 | 欧美国产激情一区二区三区蜜月 | 含羞草久久爱69一区| 激情图片小说一区| 亚洲女厕所小便bbb| 日韩免费成人网| 91久久人澡人人添人人爽欧美| 一色屋精品视频在线看| 成人少妇影院yyyy| 久久国产精品72免费观看| 伊人一区二区三区| wwww国产精品欧美| 欧美区在线观看| 亚洲免费网址| 国内精品福利| www.欧美亚洲| 老司机免费视频一区二区三区| 自拍偷拍亚洲综合| 亚洲精品在线观看视频| 欧美日韩中文字幕一区二区| 亚洲毛片一区| 牛人盗摄一区二区三区视频| 极品少妇一区二区三区精品视频| 亚洲福中文字幕伊人影院| 中文字幕一区二区三区不卡在线| 日韩欧美亚洲一区二区| 欧美日高清视频| 色88888久久久久久影院野外| 国产精品日韩一区二区三区| 国一区二区在线观看| 97精品国产露脸对白| 国产一区二区三区四| 裸体在线国模精品偷拍| 亚洲电影一级黄| 亚洲人妖av一区二区| 国产亚洲精品久| 精品国产成人系列| 日韩美女在线视频| 欧美日韩成人综合在线一区二区| 久久久蜜桃一区二区人| 国产欧美欧美| 亚洲精品激情| 欧美日韩日本网| 欧美在线视频二区| 99久久精品国产精品久久 | 欧美主播一区二区三区美女 久久精品人| 欧美在线亚洲| 99久久精品费精品国产一区二区| 国产成人aaaa| 国产一区二区0| 精品一区二区精品| 久久精品理论片| 蜜臀av性久久久久蜜臀aⅴ四虎| 午夜精品一区二区三区三上悠亚| 一区二区三区精品在线观看| 亚洲人成亚洲人成在线观看图片 | 国产精品福利一区二区| 久久久久久久久久久99999| 日韩美一区二区三区| 欧美二区三区的天堂| 欧美日韩综合不卡| 欧美色涩在线第一页| 欧美日韩精品欧美日韩精品 | 中文久久精品| 99精品国产福利在线观看免费 | 欧美一区二区三区久久精品| 91女厕偷拍女厕偷拍高清| www.久久精品| 99热精品国产| 91麻豆精品在线观看| 91丨九色丨蝌蚪富婆spa| 99精品视频在线观看| 欧美日本韩国一区二区三区| 国产精品jizz在线观看美国| 1024成人| 亚洲一区二区在线看| 久久精彩视频| 日本久久电影网| 欧美色图12p| 日韩一区二区三区四区五区六区 | 日韩高清在线观看| 美日韩一区二区| 国产一区二区三区av电影| 国产一区二区三区在线看麻豆| 成人成人成人在线视频| 色综合天天狠狠| 亚洲欧洲一区二区在线观看| 国产日韩在线一区二区三区|