在Springboot中处理log4j2日志文件过程

 更新时间:2026年01月09日 14:57:30   作者:记录Java学习的三木  
日志切割、分离和清理是日志管理的重要环节,本文介绍了在SpringBoot项目中配置日志切割、分离和清理的步骤,并详细解释了实现原理

简单介绍

日志切割

日志切割指的是将一个持续增长的、庞大的日志文件,按照某种规则分割成多个较小的、易于管理的文件。(在本配置中我们将日志按天切割,同时限制了单个日志文件不能超过64MB)

效果如图:

切割策略有两个,每天零点会将昨天的日志文件加日期保存然后生成一个新的日志文件,当天如果单个日志文件超出规定(例如本配置的64MB),会自动将此日志文件加日期保存并生成一个新的日志文件

日志分离

日志分离指的是将不同种类、不同级别或来自不同模块的日志信息,输出到不同的、独立的日志文件中。

效果如图:

日志被根据不同级别分层保存

日志清理

日志清理指的是自动删除旧的、不再需要的日志归档文件,以防止日志文件无限制地占用磁盘空间,最终导致磁盘写满。

这是生产环境中至关重要的一环。(比如本配置的清理就是会删除超过N(比如Info30天,Warn60天,Error90天)天的日志归档文件以及每个类型的日志文件总大小不超过某个GB的大小(比如Info6GB,Warn3GB,Error2GB))

如何在SpringBoot项目中配置使用

第一步,导入如下依赖到pom.xml文件当中

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>

第二步,在yaml文件中添加如下配置

logging:
  config: classpath:log4j2.xml

第三步,将xml文件放到resource目录下,下次启动项目,日志会自动被记录到logs目录(这个目录会在项目启动时自动生成)并分离清洗

xml文件名: log4j2.xml

文件代码:

<Configuration status="WARN">
    <Properties>
        <Property name="LOG_PATH">logs</Property>
        <Property name="APP_NAME">app</Property>
        <Property name="FILE_SIZE">64MB</Property>
        <Property name="LOG_PATTERN">%d{yyyy-MM-dd HH:mm:ss.SSS} %-5p [%t] %c{1.} [%X{traceId:-}] - %m%n%ex</Property>
    </Properties>
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="${LOG_PATTERN}"/>
        </Console>
        <RollingFile name="InfoFile" fileName="${LOG_PATH}/${APP_NAME}-info.log" filePattern="${LOG_PATH}/$${date:yyyy-MM}/${APP_NAME}-info-%d{yyyy-MM-dd}-%i.log">
            <Filters>
                <LevelMatchFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
            </Filters>
            <PatternLayout pattern="${LOG_PATTERN}"/>
            <Policies>
                <TimeBasedTriggeringPolicy/>
                <SizeBasedTriggeringPolicy size="${FILE_SIZE}"/>
            </Policies>
            <DefaultRolloverStrategy>
                <max>64</max>
                <Delete basePath="${LOG_PATH}" maxDepth="2">
                    <IfFileName glob="*/app-info*.log"/>
                    <IfLastModified age="30d"/>
                </Delete>
                <Delete basePath="${LOG_PATH}" maxDepth="2">
                    <IfFileName glob="*/app-info*.log"/>
                    <IfAccumulatedFileSize exceeds="6GB"/>
                </Delete>
            </DefaultRolloverStrategy>
        </RollingFile>
        <RollingFile name="WarnFile" fileName="${LOG_PATH}/${APP_NAME}-warn.log" filePattern="${LOG_PATH}/$${date:yyyy-MM}/${APP_NAME}-warn-%d{yyyy-MM-dd}-%i.log">
            <Filters>
                <LevelMatchFilter level="WARN" onMatch="ACCEPT" onMismatch="DENY"/>
            </Filters>
            <PatternLayout pattern="${LOG_PATTERN}"/>
            <Policies>
                <TimeBasedTriggeringPolicy/>
                <SizeBasedTriggeringPolicy size="${FILE_SIZE}"/>
            </Policies>
            <DefaultRolloverStrategy>
                <max>64</max>
                <Delete basePath="${LOG_PATH}" maxDepth="2">
                    <IfFileName glob="*/app-warn*.log"/>
                    <IfLastModified age="60d"/>
                </Delete>
                <Delete basePath="${LOG_PATH}" maxDepth="2">
                    <IfFileName glob="*/app-warn*.log"/>
                    <IfAccumulatedFileSize exceeds="3GB"/>
                </Delete>
            </DefaultRolloverStrategy>
        </RollingFile>
        <RollingFile name="ErrorFile" fileName="${LOG_PATH}/${APP_NAME}-error.log" filePattern="${LOG_PATH}/$${date:yyyy-MM}/${APP_NAME}-error-%d{yyyy-MM-dd}-%i.log">
            <Filters>
                <LevelMatchFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/>
            </Filters>
            <PatternLayout pattern="${LOG_PATTERN}"/>
            <Policies>
                <TimeBasedTriggeringPolicy/>
                <SizeBasedTriggeringPolicy size="${FILE_SIZE}"/>
            </Policies>
            <DefaultRolloverStrategy>
                <max>64</max>
                <Delete basePath="${LOG_PATH}" maxDepth="2">
                    <IfFileName glob="*/app-error*.log"/>
                    <IfLastModified age="90d"/>
                </Delete>
                <Delete basePath="${LOG_PATH}" maxDepth="2">
                    <IfFileName glob="*/app-error*.log"/>
                    <IfAccumulatedFileSize exceeds="2GB"/>
                </Delete>
            </DefaultRolloverStrategy>
        </RollingFile>
        <RollingFile name="DebugFile" fileName="${LOG_PATH}/${APP_NAME}-debug.log" filePattern="${LOG_PATH}/$${date:yyyy-MM}/${APP_NAME}-debug-%d{yyyy-MM-dd}-%i.log">
            <Filters>
                <LevelMatchFilter level="DEBUG" onMatch="ACCEPT" onMismatch="DENY"/>
            </Filters>
            <PatternLayout pattern="${LOG_PATTERN}"/>
            <Policies>
                <TimeBasedTriggeringPolicy/>
                <SizeBasedTriggeringPolicy size="${FILE_SIZE}"/>
            </Policies>
            <DefaultRolloverStrategy>
                <max>64</max>
                <Delete basePath="${LOG_PATH}" maxDepth="2">
                    <IfFileName glob="*/app-debug*.log"/>
                    <IfLastModified age="7d"/>
                </Delete>
                <Delete basePath="${LOG_PATH}" maxDepth="2">
                    <IfFileName glob="*/app-debug*.log"/>
                    <IfAccumulatedFileSize exceeds="5GB"/>
                </Delete>
            </DefaultRolloverStrategy>
        </RollingFile>
    </Appenders>
    <Loggers>
        <Logger name="org.springframework" level="info" additivity="false">
            <AppenderRef ref="Console"/>
            <AppenderRef ref="InfoFile"/>
            <AppenderRef ref="WarnFile"/>
            <AppenderRef ref="ErrorFile"/>
        </Logger>
        <Logger name="org.hibernate" level="warn"/>
        <Root level="info">
            <AppenderRef ref="Console"/>
            <AppenderRef ref="InfoFile"/>
            <AppenderRef ref="WarnFile"/>
            <AppenderRef ref="ErrorFile"/>
        </Root>
    </Loggers>
</Configuration>

实现原理

日志切割

Appender 就是日志的输出目的地。Appender 中的 RollingFile都设置了两种触发策略,它们之间是“或”的关系,只要满足任一条件,就会触发日志切割

  • <TimeBasedTriggeringPolicy/> 基于时间滚动,每天零点自动生成新的日志文件
  • <SizeBasedTriggeringPolicy size="${FILE_SIZE}"/> 基于文件大小的触发策略。

参数 ${FILE_SIZE}被定义为 64MB

这意味着,即使在同一天内,只要当前正在写入的日志文件大小达到 64MB,也会立即触发切割,并生成一个新的日志文件 。

            <Policies>
                <TimeBasedTriggeringPolicy/>
                <SizeBasedTriggeringPolicy size="${FILE_SIZE}"/>
            </Policies>

日志的分离

可以看到,在Appenders中RollingFile被分为了四种,分别是Info,Warn,Error,Debug级别的文件

当日志文件被切割后,其归档文件的命名和存放位置由 filePattern属性精确控制:

filePattern="${LOG_PATH}/$${date:yyyy-MM}/${APP_NAME}-info-%d{yyyy-MM-dd}-%i.log.gz"

这个配置实现了以下效果:

  • 按月份归档$${date:yyyy-MM}会在 logs目录下自动创建像 2025-03这样的子文件夹,将当月所有的归档日志文件放入其中,使目录结构非常清晰 。。
  • 索引区分:当同一天内因文件大小触发多次切割时,%i是一个从1开始递增的索引号,用于区分同一天产生的不同日志文件,例如会产生 app-info-2025-03-18-1.logapp-info-2025-03-18-2.log等文件。

日志清理

日志清理有三个策略

<max>64</max>在这里表示:当天最多可以生成 64 个归档日志文件(例如 app-info-2025-10-15-1.log.gzapp-info-2025-10-15-64.log.gz)。

当同一天内的第 65 次滚动触发时,最早的那个文件(如 ...-1.log.gz)将会被删除 。

<IfFileName glob="*/app-info*.log"/>
<IfLastModified age="30d"/>

这个代表如果超过30天会把info类型的最旧日志删除

<IfFileName glob="*/app-info*.log"/>
<IfAccumulatedFileSize exceeds="6GB"/>

这个代表如果超过6GB会把info类型的最旧日志删除

            <DefaultRolloverStrategy>
                <max>64</max>
                <Delete basePath="${LOG_PATH}" maxDepth="2">
                    <IfFileName glob="*/app-info*.log"/>
                    <IfLastModified age="30d"/>
                </Delete>
                <Delete basePath="${LOG_PATH}" maxDepth="2">
                    <IfFileName glob="*/app-info*.log"/>
                    <IfAccumulatedFileSize exceeds="6GB"/>
                </Delete>
            </DefaultRolloverStrategy>

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Java IO流之字符流的使用详解

    Java IO流之字符流的使用详解

    这篇文章主要围绕Java中的字符流进行介绍,包括字符输入流、字符输出流以及处理流异常的几种方式。文中的示例代码讲解详细,感兴趣的可以了解一下
    2022-08-08
  • Mybatis中拦截器的简单实现方法

    Mybatis中拦截器的简单实现方法

    这篇文章主要给大家介绍了关于Mybatis中拦截器的简单实现方法,文中通过示例代码介绍的非常详细,对大家学习或者使用Mybatis具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-08-08
  • java实现在原有日期时间上加几个月或几天

    java实现在原有日期时间上加几个月或几天

    这篇文章主要介绍了java实现在原有日期时间上加几个月或几天,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-10-10
  • Java开发常见错误之数值计算精度和舍入问题详析

    Java开发常见错误之数值计算精度和舍入问题详析

    除了使用Double保存浮点数可能带来精度问题外,更匪夷所思的是这种精度问题,下面这篇文章主要给大家介绍了关于Java开发常见错误之数值计算精度和舍入问题的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-11-11
  • SpringBoot使用PropertiesLauncher加载外部jar包

    SpringBoot使用PropertiesLauncher加载外部jar包

    这篇文章主要介绍了SpringBoot使用PropertiesLauncher加载外部jar包,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-07-07
  • ClassLoader类加载源码解析

    ClassLoader类加载源码解析

    这篇文章主要为大家详细解析了ClassLoader类加载源码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-09-09
  • shenyu怎么处理sign鉴权前置到网关

    shenyu怎么处理sign鉴权前置到网关

    这篇文章主要为大家介绍了shenyu怎么处理sign鉴权前置到网关方法详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-08-08
  • Springboot框架实现自动装配详解

    Springboot框架实现自动装配详解

    在使用springboot时,很多配置我们都没有做,都是springboot在帮我们完成,这很大一部分归功于springboot自动装配。本文将详细为大家讲解SpringBoot的自动装配原理,需要的可以参考一下
    2022-08-08
  • spring事务之事务挂起和事务恢复源码解读

    spring事务之事务挂起和事务恢复源码解读

    这篇文章主要介绍了spring事务之事务挂起和事务恢复源码解读,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11
  • Java连接MongoDB的常用方法详解

    Java连接MongoDB的常用方法详解

    这篇文章主要为大家详细介绍一下Java语言连接MongoDB的常用方法以及实现增删改查功能的示例代码,感兴趣的小伙伴可以跟随小编一起了解一下
    2022-07-07

最新评论