IllegalStateException : Web app root system property already set to different value问题详解

一、问题描述

    最近公司有了一个新项目,这个项目最近部署到测试服务器上的时候出现了一个问题。

严重: 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! 

    在eclipse下面启动是没问题的,打包的时候也没有报错。唯一的区别是测试服务器上tomcat里起了多个项目。

二、解决方法

    从网上找了各种资料,解决方法是在web.xml中加一段代码

<context-param>  
    <param-name>webAppRootKey</param-name>  
    <param-value>projectName.root</param-value>  <!-- 建议用"工程名字.root"-->
</context-param>  

    加了之后,果然解决了。

三、具体原因

    我是那种不找到具体原因就不甘心的人。

     首先,这个项目用到了log4j(貌似现在大部分项目都在用)。log4j启动时,默认会寻找source folder(src)下的log4j.xml配置文件,若没有,会寻找log4j.properties文件。如果log4j放到别的位置,则需要在web.xml中配置。通过log4jConfigLocation指定文件的位置。

 

  <context-param>
    <param-name>log4jConfigLocation</param-name>
    <param-value>classpath:config/log4j.properties</param-value>
  </context-param>
  <context-param>
    <param-name>log4jRefreshInterval</param-name>
    <param-value>6000</param-value>
  </context-param>
  <listener>
    <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
  </listener>

 

    问题来了,问题就出在这个org.springframework.web.util.Log4jConfigListener类里面,点进去看这个class。

public class Log4jConfigListener implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent event) {
        Log4jWebConfigurer.initLogging(event.getServletContext());
    }

    @Override
    public void contextDestroyed(ServletContextEvent event) {
        Log4jWebConfigurer.shutdownLogging(event.getServletContext());
    }

}

    再点进去initLogging这个方法。

public static void initLogging(ServletContext servletContext) {
        // Expose the web app root system property.
        if (exposeWebAppRoot(servletContext)) {
            WebUtils.setWebAppRootSystemProperty(servletContext);
        }

        // Only perform custom log4j initialization in case of a config file.
        String location = servletContext.getInitParameter(CONFIG_LOCATION_PARAM);
        if (location != null) {
            // Perform actual log4j initialization; else rely on log4j's default initialization.
            try {
                // Resolve property placeholders before potentially resolving a real path.
                location = ServletContextPropertyUtils.resolvePlaceholders(location, servletContext);

                // Leave a URL (e.g. "classpath:" or "file:") as-is.........
      .........

    再点进去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 + "]");
    }

    在这个类里面就能看到拋异常的语句以及拋异常之前处理的逻辑了。

    如果两个工程都不配webAppRootKey,第一个工程启动运行到这个ok,但是第二个工程启动的时候运行到这里,if那里就报错了。

    其实归根究底不是log4j的原因,只要涉及到这个方法,并且没有设置webAppRootKey都会报错。当启动多个工程的时候,应该要配置一下这个webAppRootKey。

 

posted @ 2016-09-30 09:36  季樊  阅读(995)  评论(0编辑  收藏  举报