WebAppRootListener使用的過程中遇到的問題
首先,先簡述一下遇到的問題,在程式中看到了這樣的一段程式碼:
String cmsRoot = System.getProperty(rootKey);
查看了一下api是這樣描述的:獲取用指定鍵描述的系統屬性
百度了一下,是這樣子的:
Java.version |
Java 執行時環境版本 |
java.vendor |
Java 執行時環境供應商 |
java.vendor.url |
Java 供應商的 URL |
java.home |
Java 安裝目錄 |
java.vm.specification.version |
Java 虛擬機器規範版本 |
java.vm.specification.vendor |
Java 虛擬機器規範供應商 |
java.vm.specification.name |
Java 虛擬機器規範名稱 |
java.vm.version |
Java 虛擬機器實現版本 |
java.vm.vendor |
Java 虛擬機器實現供應商 |
java.vm.name |
Java 虛擬機器實現名稱 |
java.specification.version |
Java 執行時環境規範版本 |
java.specification.vendor |
Java 執行時環境規範供應商 |
java.specification.name |
Java 執行時環境規範名稱 |
java.class.version |
Java 類格式版本號 |
java.class.path |
Java 類路徑 |
java.library.path |
載入庫時搜尋的路徑列表 |
java.io.tmpdir |
預設的臨時檔案路徑 |
java.compiler |
要使用的 JIT 編譯器的名稱 |
java.ext.dirs |
一個或多個擴充套件目錄的路徑 |
os.name |
作業系統的名稱 |
os.arch |
作業系統的架構 |
os.version |
作業系統的版本 |
file.separator |
檔案分隔符(在 UNIX 系統中是“/”) |
path.separator |
路徑分隔符(在 UNIX 系統中是“:”) |
line.separator |
行分隔符(在 UNIX 系統中是“/n”) |
user.name |
使用者的賬戶名稱 |
user.home |
使用者的主目錄 |
user.dir |
使用者的當前工作目錄 |
根本沒有我在程式碼中見到的這個key,然後我就在整個系統中搜這個key值,發現在web.xml中有這個key值,所以肯定是這樣影響的了,如下所示:
<!-- 以Listener方式啟動spring -->
<listener>
<listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
</listener>
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>shishuo.cms.root</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.util.WebAppRootListener</listener-class>
</listener>
但是好久不用了,忘記了context-param和listener之間的關係了,所以先複習一下web.xml中的context-param:
context-param用來宣告應用範圍(整個WEB專案)內的上下文初始化引數,這個怎麼來理解呢,其實可以根據上面這個WebAppRootListener來理解,使用Eclipse開啟WebAppRootListener的原始碼,如圖:
public class WebAppRootListener implements ServletContextListener {
public void contextInitialized(ServletContextEvent event) {
WebUtils.setWebAppRootSystemProperty(event.getServletContext());
}
public void contextDestroyed(ServletContextEvent event) {
WebUtils.removeWebAppRootSystemProperty(event.getServletContext());
}
}
contextInitialized方法是實現介面ServletContextListener中的方法,通過名稱我們可以很容易理解這是一個初始化的方法,開啟WebUtils.setWebAppRootSystemProperty方法,如下所示:
public static void setWebAppRootSystemProperty(ServletContext servletContext) throws IllegalStateException {
Assert.notNull(servletContext, "ServletContext must not be null");
String root = servletContext.getRealPath("/");
if (root == null) {
throw new IllegalStateException(
"Cannot set web app root system property when WAR file is not expanded");
}
String param = servletContext.getInitParameter(WEB_APP_ROOT_KEY_PARAM);
String key = (param != null ? param : DEFAULT_WEB_APP_ROOT_KEY);
String oldValue = System.getProperty(key);
if (oldValue != null && !StringUtils.pathEquals(oldValue, root)) {
throw new IllegalStateException(
"Web app root system property already set to different value: '" +
key + "' = [" + oldValue + "] instead of [" + root + "] - " +
"Choose unique values for the 'webAppRootKey' context-param in your web.xml files!");
}
System.setProperty(key, root);
servletContext.log("Set web app root system property: '" + key + "' = [" + root + "]");
}
這個類和方法是Spring中web包中封裝好的,所以應該是很靠譜的方法和類了,關鍵是這句話String param = servletContext.getInitParameter(WEB_APP_ROOT_KEY_PARAM);那麼WEB_APP_ROOT_KEY_PARAM又等於什麼呢,如下:
public static final String WEB_APP_ROOT_KEY_PARAM = "webAppRootKey";
原來就是我們在context-param中配置的值,這是怎麼回事呢?
因為web.xml在載入的時候會按照
context-param >> listener >> fileter >> servlet
這個順序來載入,所以context-param載入之後,就會儲存在ServletContext的例項物件中了,getInitParameter方法可以獲取到其中的值,
System.setProperty(key, root);
經過一系列的判斷,最終把這裡的值當作key來儲存應用的路徑