长期运行的应用都会产生较多的日志,如果都使用同一个文件进行存储的话,该文件会非常大,所以这就产生了需要对日志文件进行切分的需求,市场上有诸多优秀的日志框架,例如 springboot 自带的 logback 等。其中,log4j2 是其中最好的框架之一,同时 springboot 也支持了 start。
一 、简单介绍市面上的框架
两个开发日志门面。
日志门面提供了一个抽象层,使得在代码中无需硬编码具体的日志实现,增加了灵活性。
- JCL (Jakarta Commons Logging 不识闲日志功能,整合日志的)
- jdk 官方开发
- 通过 Class.loader 进行调用具体框架
- 使用举例:spring
- SLFJ
- 第三方开发
- 通过桥接器调用具体框架
- 适配器可以支持让 jcl 也使用 SLFJ 门面进行日志输出。
具体的实现框架
- Log4j 简介:Log4j 是 Apache 的一个开源项目,是最流行的 Java 日志记录工具之一。它提供了灵活的配置和强大的功能,如日志级别控制、日志旋转、异步日志记录等。 版本:Log4j 1.x 是最早的版本,Log4j 2.x 是重写后的版本,提供了更好的性能和更多的特性。 相关框架:Log4j 2.x 与 SLF4J(Simple Logging Facade for Java)紧密集成,可以通过 SLF4J 与其它日志框架桥接。
- Logback 简介:Logback 是由 Log4j 原班人马开发的一个日志框架,它旨在成为 Log4j 的替代品。Logback 与 Log4j 1.x 兼容,但提供了更好的性能和更灵活的配置。 版本:主要版本是 Logback 1.x。 相关框架:同样与 SLF4J 紧密集成。
- Log4j2 简介:Log4j2 是 Log4j 的后续版本,提供了比 Log4j 更好的性能和更多的特性,如异步日志记录、插件系统等。 版本:主要版本是 Log4j 2.x。 相关框架:Log4j2 可以直接使用,也可以通过 SLF4J 与其它日志框架桥接。
| 日志实现 | 日志门面 |
|---|---|
| Log4j | JCL |
| jul java.util.logging | SJF4J |
| log4j2 | |
| logback |
二、SpringBoot 自带的实现 SJF4J+ logback
从这张图可以看到,SpringBoot 为我们默认配置了 logback-core,以及 logback-classic、jul-to-slf4j、log4j-to-slf4j 三个适配器,可以同时支持 loback+slf4j 和 logb4j+ slf4j 的方案,而 springboot 中默认使用的就是 oback+slf4j。
三、Log4j2 配置全流程
3.1去除默认 logback
从 二 、中我们可以看到 SpirngBoot 默认为我们配置了 Logback 框架,我们这里想要使用自定义的 Log4j2框架,为了避免不必要的冲突,最好将自带的 logback 给注释掉。 以下提供两个方案,建议使用方案一进行解决。
- 注释掉整个 spring-boot-starter-logging
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
- 注释 logback的实现 logback-classic
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</exclusion>
</exclusions>
</dependency>
3.2 指定 log4j2 配置文件,并编写 log4j2.xml 文件
1.打开 application.yml 或 application.properties 文件,添加
#如下是指定 log4j2 配置文件的路径
logging:
config: classpath:log4j2.xml
#以下是指定 mybatis 或mybatis-plus 日志的实现
#mybatis
mybatis:
configuration:
log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl
#mybatis-plus配置
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl
如果不需要 sql 信息的输出,则这里不需要对 mybatis/mybatis-plus 进行配置。 !!!!!!!!!!!!!!!!!!!!!!!! 注意:这里需要注意要配置
log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl
这里需要配置为 Slf4jImpl ,而不能配置为 Log4j2 的相关实现类。
2.编写 log4j2.xml 配置文件
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
<!-- 控制台输出 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
</appender>
<!-- 按照每天生成日志文件 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志文件输出的文件名-->
<FileNamePattern>./logs/%d{yyyy-MM}/log.%d{yyyy-MM-dd}.log</FileNamePattern>
<!--日志文件保留天数-->
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
<!--日志文件最大的大小-->
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>100MB</MaxFileSize>
</triggeringPolicy>
</appender>
<!--mybatis log configure-->
<logger name="com.apache.ibatis" level="debug">
<appender-ref ref="STDOUT"/>
<appender-ref ref="FILE"/>
</logger>
<logger name="com.yinhaoinfo.wenhaoRecruit.mapper" level="debug"
>
<appender-ref ref="STDOUT"/>
<appender-ref ref="FILE"/>
</logger>
<logger name="java.sql.Connection" level="DEBUG"/>
<logger name="java.sql.Statement" level="DEBUG"/>
<logger name="java.sql.PreparedStatement" level="DEBUG"/>
<!-- 日志输出级别,logback日志级别包括五个:TRACE < DEBUG < INFO < WARN < ERROR -->
<root level="Info">
<appender-ref ref="STDOUT"/>
<appender-ref ref="FILE"/>
</root>
</configuration>
四、验证输出信息
- 有看到终端有如下输出信息即可
2024-11-02 16:06:00.446 [restartedMain] DEBUG c.y.w.mapper.OrganizationRoleMapper.selectList - ==> Preparing: SELECT id,description FROM organization_role
2024-11-02 16:06:00.446 [restartedMain] DEBUG c.y.w.mapper.OrganizationRoleMapper.selectList - ==> Preparing: SELECT id,description FROM organization_role
2024-11-02 16:06:00.458 [restartedMain] DEBUG c.y.w.mapper.OrganizationRoleMapper.selectList - ==> Parameters:
2024-11-02 16:06:00.458 [restartedMain] DEBUG c.y.w.mapper.OrganizationRoleMapper.selectList - ==> Parameters:
2024-11-02 16:06:00.484 [restartedMain] DEBUG c.y.w.mapper.OrganizationRoleMapper.selectList - <== Total: 3
2024-11-02 16:06:00.484 [restartedMain] DEBUG c.y.w.mapper.OrganizationRoleMapper.selectList - <== Total: 3
2024-11-02 16:06:00.486 [restartedMain] INFO c.y.w.common.service.DataInitServiceImpl - 完成组织角色id初始化...
2024-11-02 16:06:00.487 [restartedMain] DEBUG c.y.wenhaoRecruit.mapper.DeptRoleMapper.selectList - ==> Preparing: SELECT id,description,permissions,status,del_flag,create_by,create_time,update_by,update_time,remark FROM dept_role WHERE del_flag=0
2024-11-02 16:06:00.487 [restartedMain] DEBUG c.y.xxxx.mapper.DeptRoleMapper.selectList - ==> Preparing: SELECT id,description,permissions,status,del_flag,create_by,create_time,update_by,update_time,remark FROM dept_role WHERE del_flag=0
2024-11-02 16:06:00.487 [restartedMain] DEBUG c.y.xxxx.mapper.DeptRoleMapper.selectList - ==> Parameters:
2024-11-02 16:06:00.487 [restartedMain] DEBUG c.y.xxxx.mapper.DeptRoleMapper.selectList - ==> Parameters:
2024-11-02 16:06:00.498 [restartedMain] DEBUG c.y.xxxx.mapper.DeptRoleMapper.selectList - <== Total: 3
2024-11-02 16:06:00.498 [restartedMain] DEBUG c.y.xxxx.mapper.DeptRoleMapper.selectList - <== Total: 3
2024-11-02 16:06:00.499 [restartedMain] INFO c.y.w.common.service.DataInitServiceImpl - 完成部门角色id初始化...
2024-11-02 16:06:01.160 [restartedMain] INFO o.s.b.d.autoconfigure.OptionalLiveReloadServer - LiveReload server is running on port 35729
2. 查看文件存档。
<FileNamePattern>./logs/%d{yyyy-MM}/log.%d{yyyy-MM-dd}.log</FileNamePattern>
这里我们配置的文件存档是在当前路径下的 logs 文件夹,并按照当天时间进行分类。
五、可能出现的问题
- 终端输出日志或文件存档日志没有 mybatis 的相关查询 sql 信息。
请检查配置文件中是否填写了 log-impl,并正确配置为当前模块使用的
日志门面。
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl