Tomcat部署兩個webapp時webAppRootKey衝突的問題


問題說明

今天在部署項目時,遇到一個錯誤:
嚴重: Exception sending context initialized event to listener instance of class org.springframework.web.util.Log4jConfigListener
java.lang.IllegalStateException: Web app root system property already set to different value: 'springmvc.root' = [D:\Projects\PureWater\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\PureWaterWeixin\] instead of [D:\Projects\PureWater\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\PureWater\] - Choose unique values for the 'webAppRootKey' context-param in your web.xml files!
     at org.springframework.web.util.WebUtils.setWebAppRootSystemProperty(WebUtils.java:161)
     at org.springframework.web.util.Log4jWebConfigurer.initLogging(Log4jWebConfigurer.java:117)
     at org.springframework.web.util.Log4jConfigListener.contextInitialized(Log4jConfigListener.java:46)
     at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4812)
     at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5255)
     at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
     at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1408)
     at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1398)
     at java.util.concurrent.FutureTask.run(FutureTask.java:266)
     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
     at java.lang.Thread.run(Thread.java:745)
意思是“springmvc.root ”這個key已經指向了項目"PureWater",不能再指向另一個項目“PureWaterWeixin”。


原理分析

爲什麼會報這樣一個錯誤呢?
 
SpringMVC容器啓動時,WebAppRootListener會將該webapp的項目路徑設置到系統全局變量中,以便在可以使用系統全局變量的地方獲取到webapp的項目路徑,默認該變量名爲webapp.root,比如在log4j配置文件中使用${webapp.root} 。我們可以在web.xml中對該變量名進行自定義(任意名稱)。而且在Tomcat中,因爲其不會爲每個webapp隔離系統全局變量,我們必須在不同webapp中設置不同的變量名,否則就會出現上面的錯誤。
 
因爲我們有兩個項目都使用瞭如下相同的配置,導致“springmvc.root ”命名衝突。
 
在項目的web.xml中有一段聲明
<context-param>
    <param-name>webAppRootKey</param-name>
    <param-value>springmvc.root</param-value>
</context-param>

然後在log4j.properties對聲明的全局變量有使用
### Output to the log file ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = ${springmvc.root}/WEB-INF/logs/log.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = debug
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n

解決方案

只需要爲每個項目設置不同的名稱即可。比如,針對上面兩個代碼片段配置的名稱springmvc.root,將第一個項目改爲PureWater.root,第二個項目的名稱改爲PureWaterWeixin.root。


參考鏈接

web.xml中webAppRootKey
 
log4j和web.xml配置webAppRootKey 的問題
 
Class WebAppRootListener API
API中對webAppRootKey的原理和使用說明的非常清楚
 
WebApproot in Spring

謝謝!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章