1. 程式人生 > >logback + spring的webRootKey 多專案同時部署衝突問題

logback + spring的webRootKey 多專案同時部署衝突問題

一次部署專案後出現下面的異常:
Java程式碼 收藏程式碼
  1. java.lang.IllegalStateException: Web app root system property already set to different value: 'webapp.root' = [/usr/local/webserver/tomcat/webapps/naruto-manager/] instead of [/usr/local/webserver/tomcat/webapps/ysxj-manager/] - Choose unique values for the 'webAppRootKey' context-param in your web.xml files!  

網上很多都說是跟日誌有關
開啟logback/log4j相關的spring監聽類,比如LogbackConfigListener,初始化呼叫WebLogbackConfigurer的initLogging方法:
Java程式碼 收藏程式碼
  1. publicstaticvoid initLogging(ServletContext servletContext) {  
  2.         // Expose the web app root system property.
  3.         if (exposeWebAppRoot(servletContext)) {  
  4.             WebUtils.setWebAppRootSystemProperty(servletContext);  
  5.         }  
  6. ...  
  7. }  

追蹤到WebUtils這個類中,開啟這個類140行檢視setWebAppRootSystemProperty方法,如下
Java程式碼 收藏程式碼
  1. publicstaticvoid setWebAppRootSystemProperty(ServletContext servletContext) throws IllegalStateException {  
  2.         Assert.notNull(servletContext, "ServletContext must not be null");  
  3.         String root = servletContext.getRealPath("/"
    );  
  4.         if (root == null) {  
  5.             thrownew IllegalStateException(  
  6.                 "Cannot set web app root system property when WAR file is not expanded");  
  7.         }  
  8.         String param = servletContext.getInitParameter(WEB_APP_ROOT_KEY_PARAM);  
  9.         String key = (param != null ? param : DEFAULT_WEB_APP_ROOT_KEY);  
  10.         String oldValue = System.getProperty(key);  
  11.         if (oldValue != null && !StringUtils.pathEquals(oldValue, root)) {  
  12.             thrownew IllegalStateException(  
  13.                 "Web app root system property already set to different value: '" +  
  14.                 key + "' = [" + oldValue + "] instead of [" + root + "] - " +  
  15.                 "Choose unique values for the 'webAppRootKey' context-param in your web.xml files!");  
  16.         }  
  17.         System.setProperty(key, root);  
  18.         servletContext.log("Set web app root system property: '" + key + "' = [" + root + "]");  
  19.     }  

原因很明顯了:
Web 容器啟動的時候會獲取webAppRootKey引數的值,然後以此值為可以key 把ROOT的絕對路徑寫到系統變數裡,
如果不定義webAppRootKey引數,那麼webAppRootKey就是預設的"webapp.root",但如果多個專案都使用預設或相同的引數這裡就會報錯了
解決方法:
在web.xml中新增如下配置
Xml程式碼 收藏程式碼
  1. <context-param>
  2.     <param-name>webAppRootKey</param-name><!--如果放兩個專案例項此屬性要設定,而且兩個專案param-value值的不能相同,log4j和logback都要設定,這點很容易忽略 -->
  3.     <param-value>ysxj.root</param-value>
  4. </context-param>

這樣在logback/log4j的配置檔案中使用${ysxj.root }會用來表示Web目錄的絕對路徑