爬坑心得(二)
一、gradle經驗
1、在.gitignore檔案中,/dist/表示根目錄的dist檔案,dist/表示各子工程的dist檔案;
2、gradle拷貝檔案時,可以用exclude排除掉其中的任意檔案;
3、用gradle執行installDist時遇到了“*/bin does not exist.”這樣的報錯,在Windows平臺下不會出現這個問題,在Linux平臺下才會出現這樣的報錯,猜想應該是Linux平臺下gradle在執行installDist後預設會校驗bin目錄下的檔案,若不存在就會報錯,具體原因可能需要閱讀下gradle的原始碼,以後有空再研究吧。
二、若是報了空指標異常,這個問題其實很好解決,肯定是呼叫方為null,要麼是沒注入,要麼是空值。
三、出現了奇怪的問題,此時要從程式碼入手
1、從反編譯、IDE下載、GitHub上拷貝的方式來獲得程式碼;
2、根據錯誤日誌中的關鍵字搜尋程式碼,譬如分析程式碼中解析.properties檔案的邏輯;
3、IDEA遠端連線測試環境斷點除錯。
四、css、js靜態資源獲取不到時的除錯方法
1、降低spring boot的日誌級別logging.level.org.springframework=DEBUG;
2、單個css、js靜態資源的請求除錯,每個靜態資源的請求都會列印在DEBUG級別日誌中。
五、Spring Boot啟動時資源路徑的載入過程
1、java.exe將帶有conf和abc.jar的
2、通過Servlet工廠類AbstractEmbeddedServletContainerFactory的getUrlsOfJarsWithMetaInfResources方法從classpath中篩選出滿足條件的資源路徑放入靜態資源url的列表中;
3、將靜態資源url的列表傳遞給內嵌的應用容器Tomcat;
4、應用容器通過Tomcat類中的start方法啟動,在執行到TomcatEmbeddedServletContainer中的findContext方法時,通過斷點除錯可以看到Context中的jarResources中包括了外層到/META-INF/resources的路徑;
5、在請求檢視時,spring boot會將Context中包含/META-INF/resources的資源路徑,拼接上檢視解析器ViewResolver中配置的前後綴來找到對應的檢視資源。
六、在一個簡化的spring mvc中,127.0.0.1:8080/abc/是如何請求到對應的檢視?
1、127.0.0.1是伺服器的埠,8080是配在application.properties中的server.port=8081,abc是配在application.properties中的server.context-path=/abc/。
2、spring接收到請求後,程式可能會進行一個請求轉發,將127.0.0.1:8080/abc/轉發為127.0.0.1:8080/abc/login.do;
3、127.0.0.1:8080/abc/login.do可能會配置一個@RequestMapping來返回login檢視;
4、檢視解析器ViewResolver會依據配置好的prefix和suffix來增加前後綴,譬如WEB-INF/jsps/login.jsp;
5、spring會去尋找檢視資源,在前面加上Context中已經載入的靜態資源url,於是就成了conf或abc.jar/META-INF/resources/WEB-INF/jsps/login.jsp;
6、於是最終的請求連結其實可以理解為127.0.0.1:8080/abc/conf或abc.jar/META-INF/resources/WEB-INF/jsps/login.jsp。
七、spring boot中1.5.2.RELEASE和1.5.4.RELEASE這兩個版本的Servlet工廠類AbstractEmbeddedServletContainerFactory的getUrlsOfJarsWithMetaInfResources方法在載入staticResourceUrls靜態資源時略有差異。
1.5.2.RELEASE
1.5.4.RELEASE
多看幾遍後可以看出差異,簡單理解就是1.5.2.RELEASE版本中只判斷是否為資源jar包的isResourcesJar,如果是就放入靜態資源路徑中staticResourceUrls.add(url),但1.5.4.RELEASE進行了升級,先判斷是否為資源路徑的isResourcesDir,再判斷是否為資源jar包的isResourcesJar,只要任何一個滿足就放入靜態資源路徑中staticResourceUrls.add(url)。
這個差異對我們程式設計的改變是什麼?聰明的你一定想到了,在1.5.2.RELEASE版本中,檢視檔案只能放在jar包中META-INF/resources的路徑內,但在1.5.4.RELEASE版本中也可以放到classpath下任意一個資料夾的META-INF/resources路徑內,我們可以猜想一下spring boot版本升級後這樣完善的原因,可能是檢視資源放在jar包不方便檢視,於是也可以讓你們放到外部任何加入到classpath下的資料夾中。
PS:這裡的staticResourceUrls靜態資源指的是檢視資源,至於配置在application.properties中用於存放css、js等靜態資源的spring.resources.static-locations=classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/目前沒有出現在Context中,譬如將css、js放入static中,還需要下一步的研究。
這次在坑裡掉了很久,主要是因為對開源框架內部的執行機理不清楚,沒有認真去讀spring boot的程式碼,這也是使用開源框架的問題所在,你按照他的套路來,那麼會非常省心省力,但若想基於開源框架進行個性化的服務改造,就會遇到各種各樣的問題,主要是因為不懂內部執行機理,程式碼讀得太少。
所以,我們還是要抽空多看開原始碼,多琢磨程式碼背後的執行機理,用最近看到的一位大神的話來總結——程式設計不過是一門失傳的藝術的別名,這門藝術的名字叫“思考”。