本文将介绍 tomcat 同时启动两个 app 应用时,抛出 “java.lang.IllegalStateException: Web app root system property already set to different value: 'webapp.root' = [****] instead of [****] - Choose unique values for the 'webAppRootKey' context-param in your web.xml files!” 错误信息。具体堆栈错误日志如下:
Feb 02, 2020 9:15:21 PM org.apache.catalina.core.StandardContext listenerStart
SEVERE: 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' = [****] instead of [****] - Choose unique values for the 'webAppRootKey' context-param in your web.xml files!
at org.springframework.web.util.WebUtils.setWebAppRootSystemProperty(WebUtils.java:163)
at org.springframework.web.util.Log4jWebConfigurer.initLogging(Log4jWebConfigurer.java:119)
at org.springframework.web.util.Log4jConfigListener.contextInitialized(Log4jConfigListener.java:49)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4651)
at org.apache.catalina.core.StandardContext$1.call(StandardContext.java:5154)
at org.apache.catalina.core.StandardContext$1.call(StandardContext.java:5149)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
...
Feb 02, 2020 9:15:21 PM org.apache.catalina.core.ApplicationContext log
INFO: Initializing Spring root WebApplicationContext
Feb 02, 2020 9:15:27 PM org.apache.catalina.core.ApplicationContext log
INFO: Closing Spring root WebApplicationContext
Feb 02, 2020 9:15:27 PM org.apache.catalina.core.ApplicationContext log
INFO: Shutting down log4j解决办法:
看看上面的异常,还是挺简单的。应该是上面两个项目的设置重复了,导致出错。但我发现 web.xml 里并没有配置 webAppRootKey 项,原来是因为 web.xm 内没有设置 webAppRootKey 项,是默认设置。
public static void setWebAppRootSystemProperty(ServletContext servletContext) throws IllegalStateException {
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 ) {
throw new IllegalStateException("WARNING: Web app root system property already set: " + key + " = " +
oldValue + " - Choose unique webAppRootKey values in your web.xml files!" );
}
String root = servletContext.getRealPath("/" );
if (root == null ) {
throw new IllegalStateException("Cannot set web app root system property when WAR file is not expanded");
}
System .setProperty(key, root);
servletContext.log("Set web app root system property: " + key + " = " + root);
}从代码看出,该方法其实就是把该 web application 的根目录的绝对文件路径作为属性保存在 System 的属性列表中。该属性的名字,由 web.xml 文件中的名为 "webAppRootKey" 的参数值指出。如果不在 web.xml 中定义 webAppRootKey 参数,那么属性名就是缺省的 "webapp.root"。
现在我们需要去做的就是为两个项目定义不同当 webAppRootKey 参数,修改 web.xml 文件。如下:
项目1:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="https://java.sun.com/xml/ns/javaee"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://java.sun.com/xml/ns/javaee
https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name>myapp001</display-name>
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>myapp001.root</param-value>
</context-param>
</web-app>项目2:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="https://java.sun.com/xml/ns/javaee"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://java.sun.com/xml/ns/javaee
https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name>myapp002</display-name>
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>myapp002.root</param-value>
</context-param>
</web-app>