本文来自多个播客转载拼接而成,时间比较长,因此对于出处不能描述详尽,在此对各位作者致敬并表示歉意。
同一tomcat服务器下部署多个项目,容易发生冲突,日志文件会同时写入同一个项目的log目录中,正常情况下在一个tomcat中只会部署一个项目,此情况发生不多,但是一旦发生,需要有解决方案。
1:在web.xml中配置上下文参数
<context-param>
<param-name >webAppRootKey</param-name >
<param-value >webApp.root </param-value >
</context-param >
webAppRootKey参数为配置当前项目绝对路径,webAppRootKey值由Spring规定,固定写法。如不配置此参数,将会缺省为webApp.root,当有多个web项目共同使用同一个webApp.root值时将会互相冲突(log4g配置文件中会读取webApp.root)。
2 确保保每个项目的参数值不同,以免引起项目冲突。
对多个项目要对webAppRootKey进行配置,这里主要是让log能将日志写到对应项目根目录下,如配置这两个项目的webAppRootKey为
<!-- 应用路径 -->
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>webapp.root1</param-value>
</context-param>
==================================
<!-- 应用路径 -->
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>webapp.root2</param-value>
</context-param>
定义以后,在Web Container启动时将把ROOT的绝对路径写到系统变量里。
3 listener和contex-param
在启动Web项目时,容器(比如Tomcat)会读web.xml配置文件中的两个节点<listener>和<contex-param>。
接着容器会创建一个ServletContext(上下文),应用范围内即整个WEB项目都能使用这个上下文。
接着容器会将读取到<context-param>转化为键值对,并交给ServletContext。
容器创建<listener></listener>中的类实例,即创建监听。
Spring 通过org.springframework.web.util.WebAppRootListener 这个监听器来注入项目路径,因此部署在同一个web容器中的项目,要配置不同的param-value(比如”项目名.root”),不然会造成冲突。但是如果在web.xml中已经配置了org.springframework.web.util.Log4jConfigListener这个监听器,则不需要配置WebAppRootListener了。因为Log4jConfigListener已经包含了WebAppRootListener的功能。WebAppRootListener要在ApplicationContext的ContextLoaderListener之前,否则ApplicationContext的bean注入根目录值时会发生无法注入异常。
ServletContext读取到webapprootkey后会取到相应的k-v值如(webapp.root2),之后会以webapp.root2为key,将当前项目的绝对路径写入系统变量,因此在容器启动后,可以调用System.getProperty(“webapp.root2”)获取当前项目路径。
监听器中可调用getServletContext().getInitParameter("webapp.root2")来获取参数值。
4 容器启动log文件找不到的Exception
解决方式:将Log4jConfigListener配置放在ContextLoaderListener之前,使log4j的组件先于bean加载。