You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从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


问题分析

之前的配置存在两处关键错误:

  1. 语法错误:Property定义缺少闭合的},正确格式应为${jndi:applicationName}
  2. 循环引用与前缀错误:将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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 12:53:21