1.問題描述
tomcat中部署有兩個項目,一個ROOT.war,一個oauth.war。啟動tomcat后訪問oauth項目報404,但是ROOT項目可以正常訪問。
2.查找原因
查看日志,找到問題所在:
九月 29, 2016 6:07:51 下午 org.apache.catalina.core.StandardContext listenerStart
嚴重: 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: 'webapp.root' = [/opt/apache-tomcat-7.0.67/webapps/ROOT/] instead of [/opt/apache-tomcat-7.0.67/webapps/oauth/] - Choose unique values for the 'webAppRootKey' context-param in your web.xml files!
3.解釋原理
如果web.xml中有如下配置:
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>webapp.root</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.util.WebAppRootListener</listener-class>
</listener>
Spring通過org.springframework.web.util.WebAppRootListener 這個監(jiān)聽器將運行路徑放到系統(tǒng)變量里。
System.setProperty(key, root); //key="webapp.root" , value=該項目的物理路徑,如:"/usr/local/tomcat6/webapps/appname"
在web.xml中如果不顯式的配置參數(shù)webAppRootKey,默認值為webapp.root,在項目中可以通過以下代碼,來動態(tài)獲項目的運行路徑。
System.getProperty("webapp.root")
而部署在同一個容器中的項目,要配置不同的webAppRootKey,否則在啟動容器時,就會發(fā)生沖突,報2中的錯誤。
另外,如果在web.xml中配置 org.springframework.web.util.Log4jConfigListener這個監(jiān)聽器,它也包含了WebAppRootListener的功能。所以當在同一容器中部署多個項目時,要顯式的聲明不同的webAppRootKey,如下:
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>webapp.root</param-value>
</context-param>
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>oauth.root</param-value>
</context-param>
這樣可以在log4j.properties中配置log文件的存儲路徑:
log4j.appender.file.File=${oauth.root}/WEB-INF/logs/oauth.log