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

Spring Boot应用如何将Tomcat访问日志以JSON格式打印到控制台

问题根因

配置失效、输出乱码的核心原因有两个:

  • 你把Log4j2的日志模式占位符直接套用到了Tomcat原生访问日志的pattern配置上,两者的占位符规则完全不兼容。Tomcat AccessLogValve只识别自身定义的访问日志占位符(比如%h代表客户端IP、%t代表请求时间、%r代表请求行、%s代表响应状态码),根本不认识%d、%p、%logger、%replace这些Log4j2专属的模式语法,最终出现占位符解析失败、乱码、字段值错位。
  • 你写的server.tomcat.accesslog.console.pattern不是Spring Boot内嵌Tomcat的合法配置项,这个参数不会被识别生效。
推荐方案:桥接Tomcat访问日志到Log4j2统一输出

这个方案可以直接复用你现有的log4j2.xml JSON格式配置,不需要单独适配Tomcat的日志语法,输出格式完全统一,不会出现解析乱码、JSON非法问题。

  1. 删掉application.properties里之前写的所有server.tomcat.accesslog.*配置,关闭Tomcat原生访问日志输出。
  2. 引入Log4j2 Tomcat日志桥接依赖,Maven项目在pom.xml添加如下依赖,版本号和项目现有Log4j2版本保持一致即可:
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-appserver</artifactId>
</dependency>
  1. 在log4j2.xml中配置访问日志输出规则,和现有业务日志的JSON模板保持对齐,示例配置:
<!-- 控制台输出Appender,配置你需要的JSON结构 -->
<Appenders>
    <Console name="Console" target="SYSTEM_OUT">
        <JsonLayout properties="true" compact="false" eventEol="true">
            <KeyValuePair key="time" value="$${date:yyyy-MM-dd'T'HH:mm:ss.SSSZ}"/>
            <KeyValuePair key="level" value="${level}"/>
            <KeyValuePair key="correlation-id" value="$${ctx:X-Correlation-Id}"/>
            <KeyValuePair key="source" value="ACCESS_LOGS"/>
            <KeyValuePair key="message" value="${message}"/>
        </JsonLayout>
    </Console>
</Appenders>

<!-- 专门捕获Tomcat访问日志的Logger,绑定控制台Appender -->
<Loggers>
    <Root level="INFO">
        <AppenderRef ref="Console"/>
    </Root>
    <Logger name="org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/]" level="INFO" additivity="false">
        <AppenderRef ref="Console"/>
    </Logger>
</Loggers>
  1. 在Spring Boot启动类中注册Log4j2版的Tomcat访问日志阀:
@Bean
public TomcatServletWebServerFactory tomcatServletWebServerFactory() {
    TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
    Log4j2AccessLogValve accessLogValve = new Log4j2AccessLogValve();
    // 访问日志消息内容使用Tomcat原生占位符定义即可
    accessLogValve.setPattern("%h %l %u %t \"%r\" %s %b %Dms %{User-Agent}i %{X-Correlation-Id}i");
    factory.addContextValves(accessLogValve);
    return factory;
}

配置完成后所有Tomcat访问日志会直接走Log4j2输出管线,和业务日志格式完全统一,自动处理特殊字符转义,不会出现JSON结构破坏问题。

备选方案:使用Tomcat原生访问日志输出JSON

如果不想引入额外依赖,直接用Tomcat自带的AccessLogValve输出控制台JSON,必须严格使用Tomcat自身的占位符语法,合法配置如下:

server.tomcat.accesslog.enabled=true
server.tomcat.accesslog.directory=/dev
server.tomcat.accesslog.prefix=stdout
server.tomcat.accesslog.suffix=
server.tomcat.accesslog.file-date-format=
server.tomcat.basedir=.
# 核心:使用Tomcat合法占位符,配置项为pattern,不存在console.pattern参数
server.tomcat.accesslog.pattern="{\"time\":\"%t\",\"clientIp\":\"%h\",\"method\":\"%m\",\"uri\":\"%U\",\"query\":\"%q\",\"status\":%s,\"costMs\":%D,\"correlationId\":\"%{X-Correlation-Id}i\",\"source\":\"ACCESS_LOGS\"}%n"
server.tomcat.accesslog.encoding=UTF-8

这个方案的缺陷是无法复用Log4j2的消息转义、MDC上下文读取、异常格式化能力,如果请求参数、请求头里包含双引号、换行符等特殊字符,很容易破坏JSON结构,只适合测试环境快速验证使用。

内容的提问来源于stack exchange,提问作者acsh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 00:01:05