<Configuration status="info" monitorInterval="120"> <Properties> <Property name="logPath">${sys:webapp2.root}/../data/log</Property> </Properties> ------------- log4j2.xml里如果写固定路径,没有问题。 但是动态拼接${webapp2.root}则不识别,直接在tomcat的bin目录创建了${webapp2.root}这个目录,伤不起。
研究了很久,搜了很久,终于解决了。 ---------------------- (1)webapp2.root是web.xml里配置的 <context-param> <param-name>webAppRootKey</param-name> <param-value>webapp2.root</param-value> </context-param> 这只是一个参数。
(2)还有一个listener <listener> <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class> </listener> 这个listener启动时,会把路径设置到system属性里,大概这样: String root = servletContext.getRealPath("/"); String param = servletContext.getInitParameter("webAppRootKey"); String key = param != null ? param : "webapp.root"; System.setProperty(key, root); key就是上一步设置的参数名,不设置就默认是webapp.root。
(3)看起来没有问题,对吧。但是,log4j2.xml里就是不识别。 debug了下,发现log4j2初始化比较早, public class Log4jServletContainerInitializer implements ServletContainerInitializer 它是一个ServletContainerInitializer,比Listener先执行。 所以Listener设置的webapp.root属性,前者看不到。
(4)搜了半天,发现可以这样:
public class MyLog4jConfigListener extends Log4jConfigListener {
@Override public void contextInitialized(ServletContextEvent event) {
super.contextInitialized(event);
//log4j2初始化较早,这里设置webapp.root系统属性后,需要重载log4j,否则不能识别webapp.root org.apache.logging.log4j.core.LoggerContext ctx = (org.apache.logging.log4j.core.LoggerContext) LogManager.getContext(false); ctx.reconfigure();
} }
然后web.xml里改成这个listener,也就是设置webapp.root后,重载了下log4j2,就好使了。 (5)或者这样:${sys:catalina.home},这是tomcat根目录,用它拼也行,直接用,省事。 -------------------------------------------------- 【结果】 用了MyLog4jConfigListener后,发现有个问题, log4j2第一次初始化,会在tomcat目录建了data/log目录, 因为{webapp2.root}不识别,所以当前目录是tomcat/bin目录。
然后MyLog4jConfigListener里reconfigure后,才在正确位置创建data/log目录。 虽无大碍,但是感觉不爽。
最后查了半天,发现可以直接用 <Property name="logPath">${web:rootDir}/../data/log</Property> 这是log4j2内置的,哈哈
也不用修改MyLog4jConfigListener进行reconfigure了。 完美。
参考: https://logging.apache.org/log4j/2.x/manual/webapp.html https://logging.apache.org/log4j/2.x/manual/lookups.html#WebLookup 大概就是,log4j2,依赖webapp3.0,通过ServletContainerInitializer,实现自身自启动, 并且在spring之前启动,所以才有我那个问题。 自启动可以通过context-param来关闭,但是就得自己来启动,很麻烦。 折腾半天,就为了路径,不值得,直接用${web:rootDir}搞定,完美。
|