1、解決方案
換成XXX.class.getClassLoader().getResourceAsStream("a.txt")便可。php
2、場景復現
src/main/resource下存在文件a.txt,項目類中static 方法中讀取該文件。ClassLoader.getSystemResourceAsStream("a.txt")獲取不到資源文件html
3、緣由剖析
getResourceAsStream會先使用本類的類加載器去加載,本類沒有類加載器,纔會使用系統類加載器。也就是說getResourceAsStream功能覆蓋了getSystemResourceAsStream,因此推薦直接使用getResourceAsStream就完事了。都不須要知道具體二者有啥區別。java
下面咱們來細看有啥區別....web
3.1 java類加載器
![](http://static.javashuo.com/static/loading.gif)
- 1.啓動類加載器(Bootstrap ClassLoader):頂層的類加載器,沒有父類加載器。負責加載 /lib 目錄下的,或被 -Xbootclasspath 參數所指定路徑中的,並被 JVM 識別的(僅按文件名識別,如 rt.jar,名字不符合的類庫即便放在 lib 目錄也不會被加載)類庫加載到虛擬機內存中。全部被 Bootstrap classloader 加載的類,它的 Class.getClassLoader 方法返回的都是 null,因此也稱做 NULL ClassLoader。
- 2.擴展類加載器(Extension CLassLoader):由 sun.misc.Launcher$ExtClassLoader 實現,負責加載 <JAVA_HOME>/lib/ext 目錄下,或被 java.ext.dirs 系統變量所指定的目錄下的全部類庫;
- 3.應用程序類加載器(Application/System ClassLoader):由 sun.misc.Launcher$AppClassLoader 實現。它是 ClassLoader.getSystemClassLoader() 方法的默認返回值,因此也稱爲系統類加載器(System ClassLoader)。它負責加載 classpath 下所指定的類庫,若是應用程序沒有自定義過本身的類加載器,通常狀況下這個就是程序中默認的類加載器。
3.2 tomcat容器下類加載器
Tomcat官方說明:Class Loader HOW-TO
apache
跟普通的java程序相比,類加載大致順序相同。bootstrap
![](http://static.javashuo.com/static/loading.gif)
- 1.Bootstrap 啓動類加載器: 加載JVM啓動所需的類+系統擴展目錄($JAVA_HOME/jre/lib/ext)裏 JAR 文件中的類。
- 2.System 系統類加載器:從 CLASSPATH 系統變量指定的目錄中加載類庫。該加載器加載的類對 tomcat 自己和 web 應用均可見。可是,標準的 tomcat 啓動腳本($CATALINA_HOME/bin/catalina.sh or %CATALINA_HOME%\bin\catalina.bat)都會忽略系統變量 CLASSPATH 的值,而會使用以下的類庫來建立 System 類加載器:
$CATALINA_HOME/bin/bootstrap.jartomcat
$CATALINA_BASE/bin/tomcat-juli.jar 或 $CATALINA_HOME/bin/tomcat-juli.jarapp
$CATALINA_HOME/bin/commons-daemon.jarspa
- 3.Common 通用類加載器:經過該類加載器加載的類庫可被 Tomcat 和全部應用共享。該類加載器的搜索位置是經過 $CATALINA_BASE/conf/catalina.properties 文件中的 common.loader 屬性指定的,默認包括以下位置:
$CATALINA_BASE/lib 下未打包的類和資源;.net
$CATALINA_BASE/lib 下的 jar 包;
$CATALINA_HOME/lib 下未打包的類和資源;
$CATALINA_HOME/lib 下的 jar 包。
- 4.WebappX 應用類加載器:每一個 Web 應用建立一個本身的類加載器,加載本身項目下的數據: /WEB-INF/classes 和 /WEB-INF/lib 下的類和資源。而且不使用雙親委派機制,先本身加載,加載不到才使用父類加載器。
原本順序是1234,可是WebappX不使用委派機制而是先本身加載,加載不了才使用父類,因此真實的順序是:
- Bootstrap classes of your JVM
- /WEB-INF/classes of your web application
- /WEB-INF/lib/*.jar of your web application
- System class loader classes (described above)
- Common class loader classes (described above)
tomcat8支持委託:配置容許委派:<Loader delegate="true"/>,順序變爲:
- Bootstrap classes of your JVM
- System class loader classes (described above)
- Common class loader classes (described above)
- /WEB-INF/classes of your web application
- /WEB-INF/lib/*.jar of your web application
3.3 問題迴歸
tomcat容器中運行的java程序,使用系統類加載器是不能獲取到資源的,必須使用WebappClassLoader。使用getResourceAsStream獲取當前類的類加載器,也就是WebappClassLoader,天然能夠獲取到資源了。
=======參考=========
https://blog.csdn.net/w1196726224/article/details/54428493