从Tomcat server.xml获取Context参数配置Log4j2实现分WAR日志目录
从Tomcat Context参数生成Log4j2独立日志目录
问题场景
需要从Tomcat server.xml的Host节点下的Context参数读取applicationName,配置到Log4j2中,为每个部署的WAR包生成独立日志目录。相关配置及期望效果如下:
Tomcat server.xml配置
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true"> <Context path="/App1" docBase="/opt/xx/deployments/App1.war" distributable="true"> <Parameter name="applicationName" value="app1" /> </Context> <Context path="/App2" docBase="/opt/xx/deployments/App2.war" distributable="true"> <Parameter name="applicationName" value="app2" /> </Context> </Host>
期望效果
Tomcat启动后生成独立日志路径:
./logs/app1/app1.log./logs/app2/app2.log
之前的错误配置及问题
在log4j2.xml中添加了错误配置:
<Property name="applicationName">$${jndi:applicationName</Property>
并将fileName设置为${sys:applicationName}/${sys:applicationName}.log,启动后收到警告:WARN Infinite loop in property interpolation of applicationName->jndi:applicationName
问题分析
之前的配置存在两处关键错误:
- 语法错误:Property定义缺少闭合的
},正确格式应为${jndi:applicationName} - 循环引用与前缀错误:将Property命名为
applicationName,同时引用同名JNDI变量,导致插值循环;另外sys:前缀对应系统属性,而此处参数是Tomcat Context参数,不属于系统属性,不能使用该前缀。
正确配置方案
1. 保留Tomcat Context参数配置
server.xml中的Context配置无需修改,Tomcat会自动将<Parameter>注入到对应Web应用的ServletContext中,也可通过JNDI访问。
2. 修改Log4j2配置文件
无需定义同名Property,直接在日志路径中引用Context参数,以下两种方式任选其一:
方式一:通过ServletContext属性(推荐)
使用${ctx:applicationName}直接引用ServletContext中的属性,这是获取Tomcat Context参数最直接的方式:
<Appenders> <RollingFile name="AppRollingFile" fileName="logs/${ctx:applicationName}/${ctx:applicationName}.log" filePattern="logs/${ctx:applicationName}/%d{yyyy-MM-dd}-%i.log.gz"> <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/> <SizeBasedTriggeringPolicy size="100MB"/> <DefaultRolloverStrategy max="10"/> </RollingFile> </Appenders> <Loggers> <Root level="info"> <AppenderRef ref="AppRollingFile"/> </Root> </Loggers>
方式二:通过JNDI引用
直接使用${jndi:applicationName}引用JNDI环境中的参数,注意不要定义同名Property避免循环:
<Appenders> <RollingFile name="AppRollingFile" fileName="logs/${jndi:applicationName}/${jndi:applicationName}.log" filePattern="logs/${jndi:applicationName}/%d{yyyy-MM-dd}-%i.log.gz"> <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/> <SizeBasedTriggeringPolicy size="100MB"/> <DefaultRolloverStrategy max="10"/> </RollingFile> </Appenders> <Loggers> <Root level="info"> <AppenderRef ref="AppRollingFile"/> </Root> </Loggers>
3. 注意事项
- 将log4j2.xml放置在Web应用的
WEB-INF/classes目录下,确保Web应用启动时能正确加载 - Log4j2的RollingFileAppender会自动创建不存在的日志目录,无需手动创建
- 若使用Tomcat全局Log4j2配置,需确保全局配置能识别每个Web应用的独立Context参数,更推荐使用Web应用专属的Log4j2配置
内容的提问来源于stack exchange,提问作者fBruno
相关产品推荐
相关产品推荐

