最近了解到新的日志模式,Log4j2+slfj4的日志模式,比起SpringBoot自带的LogBack日志效率要高上许多,今天对Springboot集合Log4j2+slfj4的日志模式进行基础讲解和使用
首先简单讲解一下日志系统Log4j2,该系统前身是Log4j,SpringBoot自带的LogBack可以看作Log4j的同类型作品,而Log4j2是Log4j2的升级版,在各个方面都有远超前代的效率。
在开始前的准备工具有:
完成SpringBoot基础框架的搭建
完成准备工具后我们可以正式开始讲解,首先引入Log4j2和slfj4的相关依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<!-- 加上这个才能辨认到log4j2.yml文件 -->
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-yaml</artifactId>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-web</artifactId>
<version>2.9.1</version>
</dependency>
<!--用于与slf4j保持桥接-->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.9.1</version>
</dependency>
<!-- slf4j核心包-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
因为我们需要取代Springboot本身的日志,所以我们需要在web依赖中取消掉自带的Logback日志
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
<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-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
完成相关依赖注入后,我们在src/main/java/resources文件下新建application-log4j2.yml配置文件,引入Log4j2的相关配置
# 共有8个级别,按照从低到高为:ALL < TRACE < DEBUG < INFO < WARN < ERROR < FATAL < OFF。
Configuration:
status: info
monitorInterval: 30
Properties: # 定义全局变量
Property: # 缺省配置(用于开发环境)。其他环境需要在VM参数中指定,如下:
#测试:-Dlog.level.console=warn -Dlog.level.xjj=trace
#生产:-Dlog.level.console=warn -Dlog.level.xjj=info
- name: log.level.console
value: info
- name: log.path
value: log
- name: project.name
value: opendoc
- name: log.pattern
value: "%d{yyyy-MM-dd HH:mm:ss.SSS} -%5p ${PID:-} [%15.15t] %-30.30C{1.} : %m%n"
Appenders:
Console: #输出到控制台
name: CONSOLE
target: SYSTEM_OUT
PatternLayout:
pattern: ${log.pattern}
# 启动日志
RollingFile:
- name: ROLLING_FILE
fileName: ${log.path}/${project.name}.log
filePattern: "${log.path}/historyRunLog/$${date:yyyy-MM}/${project.name}-%d{yyyy-MM-dd}-%i.log.gz"
PatternLayout:
pattern: ${log.pattern}
Filters:
# 一定要先去除不接受的日志级别,然后获取需要接受的日志级别
ThresholdFilter:
- level: error
onMatch: DENY
onMismatch: NEUTRAL
- level: info
onMatch: ACCEPT
onMismatch: DENY
Policies:
TimeBasedTriggeringPolicy: # 按天分类
modulate: true
interval: 1
DefaultRolloverStrategy: # 文件最多100个
max: 100
# 平台日志
- name: PLATFORM_ROLLING_FILE
ignoreExceptions: false
fileName: ${log.path}/platform/${project.name}_platform.log
filePattern: "${log.path}/platform/$${date:yyyy-MM}/${project.name}-%d{yyyy-MM-dd}-%i.log.gz"
PatternLayout:
pattern: ${log.pattern}
Policies:
TimeBasedTriggeringPolicy: # 按天分类
modulate: true
interval: 1
DefaultRolloverStrategy: # 文件最多100个
max: 100
# 业务日志
- name: BUSSINESS_ROLLING_FILE
ignoreExceptions: false
fileName: ${log.path}/bussiness/${project.name}_bussiness.log
filePattern: "${log.path}/bussiness/$${date:yyyy-MM}/${project.name}-%d{yyyy-MM-dd}-%i.log.gz"
PatternLayout:
pattern: ${log.pattern}
Policies:
TimeBasedTriggeringPolicy: # 按天分类
modulate: true
interval: 1
DefaultRolloverStrategy: # 文件最多100个
max: 100
# 错误日志
- name: EXCEPTION_ROLLING_FILE
ignoreExceptions: false
fileName: ${log.path}/exception/${project.name}_exception.log
filePattern: "${log.path}/exception/$${date:yyyy-MM}/${project.name}-%d{yyyy-MM-dd}-%i.log.gz"
ThresholdFilter:
level: error
onMatch: ACCEPT
onMismatch: DENY
PatternLayout:
pattern: ${log.pattern}
Policies:
TimeBasedTriggeringPolicy: # 按天分类
modulate: true
interval: 1
DefaultRolloverStrategy: # 文件最多100个
max: 100
# DB 日志
- name: DB_ROLLING_FILE
ignoreExceptions: false
fileName: ${log.path}/db/${project.name}_db.log
filePattern: "${log.path}/db/$${date:yyyy-MM}/${project.name}-%d{yyyy-MM-dd}-%i.log.gz"
PatternLayout:
pattern: ${log.pattern}
Policies:
TimeBasedTriggeringPolicy: # 按天分类
modulate: true
interval: 1
DefaultRolloverStrategy: # 文件最多100个
max: 100
Loggers:
Root:
level: info
AppenderRef:
- ref: CONSOLE
- ref: ROLLING_FILE
- ref: EXCEPTION_ROLLING_FILE
Logger:
- name: platform
level: info
additivity: false
AppenderRef:
- ref: CONSOLE
- ref: PLATFORM_ROLLING_FILE
- name: bussiness
level: info
additivity: false
AppenderRef:
- ref: BUSSINESS_ROLLING_FILE
- name: exception
level: debug
additivity: true
AppenderRef:
- ref: EXCEPTION_ROLLING_FILE
- name: db
level: info
additivity: false
AppenderRef:
- ref: DB_ROLLING_FILE
完成application-log4j2.yml配置文件后,在主配置文件中将log4j2文件配置加载进来
logging:
config: classpath:application-log4j2.yml
Log4j2配置文件有以下关键节点
Configuration:根节点,具有status和monitorInterval等常用属性
status:日志等级,等级越低,日志越详细,等级越高,日志只会记录关键信息,从低到高包容,日志等级分别为trace、debug、info、warn、error和 fatal,一般使用warn足够应付大部分情况
monitorlnterval:每隔多少秒从读配置文件,可以在不重启的情况下更改配置文件
properties:配置文件全局的安全变量,减少自定义配置信息的重复编码,可以指定日志的存放位置,如果不指定日志的存放位置,默认存放在Springboot项目的文件目录下
Appenders:输出源,用于指定日志输出的地方,具有以下常用属性
Console:控制台输出源是将日志打印到控制台上,开发的时候一般都会配置,以便调试
RollingRandomAccessFile: 文件输出源,将日志写入到指定文件,当文件写入到一定大小时,新建一个文件写入,需要配合文件命名规则使用
fileName:指定当前日志文件的位置和文件名称
filePattern:指定当发生Rolling时,文件的转移和重命名规则
SizeBasedTriggeringPolicy:指定当文件体积大于size指定的值时,触发Rolling
DefaultRolloverStrategy:指定最多保存的文件个数
TimeBasedTriggeringPolicy 这个配置需要和filePattern结合使用,注意filePattern中配置的文件重命名规则是${FILE_NAME}-%d{yyyy-MM-dd HH-mm}-%i,最小的时间粒度是mm,即分钟
TimeBasedTriggeringPolicy指定的size是1,结合起来就是每1分钟生成一个新文件。如果改成%d{yyyy-MM-dd HH},最小粒度为小时,则每一个小时生成一个文件
RollingFile:同上,与RollingRandomAccessFile不同的是,RollingRandomAccessFile默认日志文件写入策略为异步刷盘,RollingRandomAccessFile会将日志信息先写入到缓冲区,然后缓冲区满后刷到磁盘,并清空缓冲区,默认缓冲区的大小在8-256kb,具体大小需要自己设置。
Async:异步,需要通过AppenderRef来指定要对哪种输出源进行异步(一般用于配置RollingRandomAccessFile)
PatternLayout:控制台或文件输出源(Console、File、RollingRandomAccessFile)都必须包含一个PatternLayout节点,用于指定输出文件的格式(如日志输出的时间、文件、方法、行数等格式),例如pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n",各标记符详细含义如下:
各个标识符含义如下
%d{HH:mm:ss.SSS} 表示输出到毫秒的时间
%t 输出当前线程名称
%-5level 输出日志级别,-5表示左对齐并且固定输出5个字符,如果不足在右边补0
%logger 输出logger名称,因为Root Logger没有名称,所以没有输出
%msg 日志文本
%n 换行
Logger:日志器,分为根日志器root和自定义日志器,具有以下属性
name:日志器名称
leveal:日志级别
additivity:是否同时输出log到父类的appender,缺省为true
AppenderRef:输出源
到这里Log4j2的配置讲解结束,我们来看看实际效果

更具上诉图片可以看到我的日志等级为INFO,后面的控制台输出如图所示
因为我们没有指定日志文件的存储位置,所以默认在我们项目的文件夹下


这样我们就成功使用Log4j2日志取代了Logback日志,接下来是slf4j的使用演示
package com.example.testlog.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.testlog.dao.UserDao;
import com.example.testlog.entity.User;
import com.example.testlog.service.UserService;
import lombok.AllArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
@AllArgsConstructor
public class UserImpl implements UserService {
private final UserDao userDao;
private static final Logger LOGGER = LoggerFactory.getLogger(UserImpl.class);
@Override
public List<User> list() {
QueryWrapper<User> wrapper = new QueryWrapper<>();
List<User> list = userDao.selectList(wrapper);
LOGGER.info("日志测试");
return list;
}
}
打印日志

可以看到测试成功
本博客参考了Log4j2使用详解 - 知乎 (zhihu.com)相关内容
看到这里的同学点个赞吧!