springboot 在idea多模組下 子模組的web專案用內建tomcat啟動訪問jsp報404
問題描述:最近公司換spring boot 做微服務開發。多個微服務按模組匯入匯入到idea。之前是單獨的專案匯入。能正常啟動和正常訪問。換到idea的專案--模組結構之後。發現用內建tomcat啟動web專案無法訪問到jsp頁面了。(ps:打成war包到外面tomcat啟動是沒有問題。只是不服,發現這個奇葩的問題沒找到原因心中不爽。)
問題分析:無法訪問jsp,很自然想到:一是路徑有沒有對映對?二是檔案不存在。檢查一遍之後發現對映沒有問題,檔案也存在。這就比較奇葩了。唯有看一下springboot在啟動的時候如何定義web root的路徑。跟一下springboot的tomcat啟動包的原始碼:
/**
* Returns the absolute document root when it points to a valid directory, logging a
* warning and returning {@code null} otherwise.
* @return the valid document root
*/
protected final File getValidDocumentRoot() {
File file = getDocumentRoot();
// If document root not explicitly set see if we are running from a war archive
file = file != null ? file : getWarFileDocumentRoot();
// If not a war archive maybe it is an exploded war
file = file != null ? file : getExplodedWarFileDocumentRoot();
// Or maybe there is a document root in a well-known location
file = file != null ? file : getCommonDocumentRoot();
if (file == null && this.logger.isDebugEnabled()) {
this.logger
.debug("None of the document roots " + Arrays.asList(COMMON_DOC_ROOTS)
+ " point to a directory and will be ignored.");
}
else if (this.logger.isDebugEnabled()) {
this.logger.debug("Document root: " + file);
}
return file;
}
發現有三種取路徑方式。war包 getWarFileDocumentRoot,匯出包 getExplodedWarFileDocumentRoot,和文件 getCommonDocumentRoot。內建tomcat啟動應該屬於第三種。跟進去第三種發現:
private static final String[] COMMON_DOC_ROOTS = { "src/main/webapp", "public",
"static" };
private File getCommonDocumentRoot() {
for (String commonDocRoot : COMMON_DOC_ROOTS) {
File root = new File(commonDocRoot);
if (root != null && root.exists() && root.isDirectory()) {
return root.getAbsoluteFile();
}
}
return null;
}
寫死從上面配置的3個目錄去取doc路徑。
看到這裡問題就明瞭。關鍵是
File root = new File(commonDocRoot);
if (root != null && root.exists() && root.isDirectory()) {
return root.getAbsoluteFile();
}
File root = new File("src/main/webapp") 的是 這個相對路徑的字首是取哪裡的。
百度得知 取的是
System.getProperty("user.dir")
相當於 File root = new File(System.getProperty("user.dir")+"src/main/webapp");
然後 debug 列印一下 System.getProperty("user.dir") 發現 是定位到了 專案那層 而不是模組那層
解決方法:既然發現了問題,解決就簡單。這裡採用的是直接在啟動項裡面增加配置引數,將"user.dir" 定位到模組裡面。
問題解決。
最後:因為對tomcat的啟動順序不瞭解。跟這個過程的時候走了不少彎路。採用了最笨的方法,在後面層層倒推一直找到上面設定doc路徑的方法。如果熟悉原理,直接從開始就定位到那個方法就很快能解決了。所以記錄下來。避免自己或有遇到同樣問題的人少走彎路。