SpringBoot之slf4j、log4j、logback应用
1. slf4j、log4j、logback是什么?
1.1 slf4j(simple logging facade for java)
SLF4J
意为 Java 简单日志门面,它是把不同的日志系统的实现进行了具体的抽象化,只提供了统一的日志使用接口,使用时只需要按照其提供的接口方法进行调用即可。
由于SLF4J
只是一个接口,不是具体的日志框架,使用的时候需要绑定具体的日志框架,才能实现具体的日志功能,这些具体的日志系统就有log4j
、logback
、java.util.logging
等,它们才实现了具体的日志系统的功能。
1.2 log4j(log for java)
Log4j
是 Apache 的一个开源项目,通过使用Log4j
,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件,甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。
1.3 logback
logback
同样是由 log4j 的作者设计完成的,拥有更好的特性,用来取代 log4j 的一个日志框架,是slf4j
的原生实现。(即直接实现了slf4j
的接口,而log4j
并没有直接实现,所以就需要一个适配器slf4j-log4j12.jar
),logback一共有以下几个模块:
logback-core
:其它两个模块的基础模块logback-classic
:它是 log4j 的一个改良版本,同时它完整实现了slf4j API,使你可以很方便地更换成其它日志系统,如 log4j 或 JDK14 Logginglogback-access
:访问模块与 Servlet 容器集成提供通过 Http 来访问日志的功能
同样,单独使用它时,需要引入以上 jar,然后进行配置文件的配置,最后就是在相关类中进行使用。
联系
SLF4J
原理很简单,他只提供一个核心包:slf4j-api.jar
,结合其他框架 jar 包情况为:
- SLF4J 和 logback 结合:slf4j-api.jar、logback-classic.jar、logback-core.jar
- SLF4J 和 log4j 结合:slf4j-api.jar、slf4j-log4j.jar、log4j.jar
- SLF4J 和 JDK中java.util.logging 结合:slf4j-api.jar、slf4j-jdk14.jar
使用
为什么要使用SLF4J?
- slf4j是一个日志接口,自己没有具体实现日志系统,只提供了一组标准的调用api,这样将调用和具体的日志实现分离,使用slf4j后有利于根据自己实际的需求更换具体的日志系统,比如,之前使用的具体的日志系统为log4j,想更换为logback时,只需要删除log4j相关的jar,然后加入logback相关的jar和日志配置文件即可,而不需要改动具体的日志输出方法。
- 如果你开发的是一个面向公众使用的组件或公共服务模块,那么一定要使用slf4的这种形式,这有利于别人在调用你的模块时保持和他系统中使用统一的日志输出。
- slf4j日志输出时可以使用{}占位符,如,
logger.info("testlog: {}", "test")
,而如果只使用log4j做日志输出时,只能以logger.info("testlog:"+"test")
这种形式,前者要比后者在性能上更好,后者采用+连接字符串时就是new 一个String 字符串,在性能上就不如前者。
log4j、logback 均是具体的日志框架,可以单独使用,也可以结合 slf4j 使用。单独使用,分别调用框架自己的方法来输出日志信息;绑定 slf4j 一起使用,调用 slf4j 的 api 来输入日志信息。
考虑到日志代码与日志框架的解耦,需要使用 slf4j;考虑到日志功能对设备性能的影响,选用 logback;故可以使用组合slf4j + logback
。
2. logback使用步骤
2.1 加入依赖
Logback 使用 Java 的简单日志记录外观(SLF4J)作为其接口。我们需要将 Logback 和 SLF4J 所需 Jar
pom.xml:
<!-- slf4j -->
<dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.30</version><scope>test</scope>
</dependency><!-- logback -->
<dependency><groupId>ch.qos.logback</groupId><artifactId>logback-core</artifactId><version>1.2.6</version>
</dependency>
<dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.2.6</version>
</dependency>
2.2 加入logback.xml配置文件
将logback.xml
加入到项目的 resource 目录下。
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="10 seconds"><!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出 --><!-- scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true --><!-- scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。 --><!-- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 --><contextName>logback</contextName><!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量。 --><!-- 项目路径,可用绝对路径,也可用相对路径,如下是用的相对路径 --><property name="log.path" value="Log" /><!-- 彩色日志 --><!-- 配置格式变量:CONSOLE_LOG_PATTERN 彩色日志格式 --><!-- magenta:洋红 --><!-- boldMagenta:粗红--><!-- cyan:青色 --><!-- white:白色 --><!-- magenta:洋红 --><property name="CONSOLE_LOG_PATTERN"value="%yellow(%date{yyyy-MM-dd HH:mm:ss}) |%highlight(%-5level) |%blue(%thread) |%blue(%file:%line) |%green(%logger) |%cyan(%msg%n)"/><!--输出到控制台--><appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"><!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息--><!-- 例如:如果此处配置了INFO级别,则后面其他位置即使配置了DEBUG级别的日志,也不会被输出 --><filter class="ch.qos.logback.classic.filter.ThresholdFilter"><level>INFO</level></filter><encoder><Pattern>${CONSOLE_LOG_PATTERN}</Pattern><!-- 设置字符集 --><!-- <charset>UTF-8</charset>--></encoder></appender><!--输出到文件--><!-- 时间滚动输出 level为 INFO 日志 --><appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"><!-- 正在记录的日志文件的路径及文件名 --><file>${log.path}/log_info.log</file><!--日志文件输出格式--><encoder><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern><!-- <charset>UTF-8</charset>--></encoder><!-- 日志记录器的滚动策略,按日期,按大小记录 --><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!-- 每天日志归档路径以及格式 --><fileNamePattern>${log.path}/info/log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern><timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"><maxFileSize>100MB</maxFileSize></timeBasedFileNamingAndTriggeringPolicy><!--日志文件保留天数--><maxHistory>15</maxHistory></rollingPolicy><!-- 此日志文件只记录info级别的 --><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>INFO</level><onMatch>ACCEPT</onMatch><onMismatch>DENY</onMismatch></filter></appender><!-- 时间滚动输出 level为 WARN 日志 --><appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"><!-- 正在记录的日志文件的路径及文件名 --><file>${log.path}/log_warn.log</file><!--日志文件输出格式--><encoder><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern><!-- <charset>UTF-8</charset> --><!-- 此处设置字符集 --></encoder><!-- 日志记录器的滚动策略,按日期,按大小记录 --><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>${log.path}/warn/log-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern><timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"><maxFileSize>100MB</maxFileSize></timeBasedFileNamingAndTriggeringPolicy><!--日志文件保留天数--><maxHistory>15</maxHistory></rollingPolicy><!-- 此日志文件只记录warn级别的 --><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>warn</level><onMatch>ACCEPT</onMatch><onMismatch>DENY</onMismatch></filter></appender><!-- 时间滚动输出 level为 ERROR 日志 --><appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"><!-- 正在记录的日志文件的路径及文件名 --><file>${log.path}/log_error.log</file><!--日志文件输出格式--><encoder><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern><!-- <charset>UTF-8</charset> --><!-- 此处设置字符集 --></encoder><!-- 日志记录器的滚动策略,按日期,按大小记录 --><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>${log.path}/error/log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern><timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"><maxFileSize>100MB</maxFileSize></timeBasedFileNamingAndTriggeringPolicy><!--日志文件保留天数--><maxHistory>15</maxHistory></rollingPolicy><!-- 此日志文件只记录ERROR级别的 --><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>ERROR</level><onMatch>ACCEPT</onMatch><onMismatch>DENY</onMismatch></filter></appender><!--<logger>用来设置某一个包或者具体的某一个类的日志打印级别、以及指定<appender>。<logger>仅有一个name属性,一个可选的level和一个可选的addtivity属性。name:用来指定受此logger约束的某一个包或者具体的某一个类。level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,如果未设置此属性,那么当前logger将会继承上级的级别。--><!--使用mybatis的时候,sql语句是debug下才会打印,而这里我们只配置了info,所以想要查看sql语句的话,有以下两种操作:第一种把<root level="INFO">改成<root level="DEBUG">这样就会打印sql,不过这样日志那边会出现很多其他消息第二种就是单独给mapper下目录配置DEBUG模式,代码如下,这样配置sql语句会打印,其他还是正常DEBUG级别:--><!--开发环境:打印控制台--><springProfile name="dev"><!--可以输出项目中的debug日志,包括mybatis的sql日志--><logger name="com.guli" level="INFO" /><!--root节点是必选节点,用来指定最基础的日志输出级别,只有一个level属性level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,默认是DEBUG可以包含零个或多个appender元素。--><root level="INFO"><appender-ref ref="CONSOLE" /><appender-ref ref="INFO_FILE" /><appender-ref ref="WARN_FILE" /><appender-ref ref="ERROR_FILE" /></root></springProfile><!--生产环境:输出到文件--><springProfile name="pro"><root level="INFO"><appender-ref ref="CONSOLE" /><appender-ref ref="DEBUG_FILE" /><appender-ref ref="INFO_FILE" /><appender-ref ref="ERROR_FILE" /><appender-ref ref="WARN_FILE" /></root></springProfile>
</configuration>
logback配置属性详解:
- 根节点<configuration>
<configuration scan="true" scanPeriod="60 seconds" debug="false"> <!-- 其他配置省略-->
</configuration>
- scan : 当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。
- scanPeriod : 设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。
- debug : 当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。
- 子节点<property>
<property name="log.path" value="Log" />
用来定义变量值的标签,定义变量后,可以使${}
来使用变量。
- name:变量的名称
- value:变量定义的值
注:多环境配置下,通过 application.yml 传递参数过来,<property>
取不到环境参数,得用<springProperty>
。
<springProperty scope="context" name="APP_NAME" source="spring.application.name" defaultValue="springBoot"/>
- 子节点<appender>
appender用来格式化日志输出,
- name:名称
- class:class用来指定哪种输出策略,常用就是控制台输出策略
ConsoleAppender
和文件输出策略RollingFileAppender
。
ConsoleAppender
将日志信息打印到控制台上,更加准确的说:使用System.out或者System.err方式输出,主要子标签有:filter、encoder
FileAppender
用于将日志信息输出到文件中,主要子标签有:append,encoder,file。
RollingFileAppender
RollingFileAppender
继承FIleAppender
。功能:能够动态的创建一个文件。也就是说:到满足一定的条件,就会创建一个新的文件,然后将日志写入到新的文件中。有两个重要的标签与RollingFileAppender进行交互:RollingPolicy
、TriggeringPolicy
,主要子标签:file,append,encoder,rollingPolicy,triggerPolicy
以下分别介绍这些标签:
file
被写入的文件名,可以是相对目录,也可以是绝对目录,如果上级目录不存在会自动创建,没有默认值。
append
如果是 true,日志被追加到文件结尾,如果是 false,清空现存文件,默认是true
。
encoder
<!-- 控制台设置 --><appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender"><encoder><!--<pattern>%d %p (%file:%line\\)- %m%n</pattern>--><!--格式化输出:%d:表示日期 %thread:表示线程名 %-5level:级别从左显示5个字符宽度 %msg:日志消息 %n:是换行符--><pattern>%boldMagenta(笑小枫控制台-) %red(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %yellow(%logger) - %cyan(%msg%n)</pattern><charset>UTF-8</charset></encoder></appender>
filter
当满足过滤器指定的条件时,才记录日志(不满足条件时,拒绝记录日志)。logback 支持自定义过滤器,当然 logback 也自带了一些常用的过滤器,在绝大多数时候,自带的过滤器其实就够用了,一般是不需要自定义过滤器的。
过滤器 | 来源 | 说明 | 相对常用 |
---|---|---|---|
LevelFilter | Filter | 对指定 level 的日志进行记录,对不等于指定 level 的日志不记录 | 是 |
ThresholdFilter | Filter | 对大于或等于指定 level 的日志进行记录,对小于指定 level 的日志不记录 | 是 |
EvaluatorFilter | Filter | 对满足指定表达式的日志进行记录,对不满足指定表达式的日志不作记录 | 是 |
MarkerFilter | TurboFilter | 针对带有指定标记的日志,进行记录(或不作记录) | 否 |
rollingPolicy
https://zhuanlan.zhihu.com/p/612724441
https://blog.csdn.net/sunzixiao/article/details/126256484
小结
- slf4j 是 java 的一个日志门面,实现了日志框架一些通用的api,log4j 和 logback 是具体的日志框架。
- 他们可以单独的使用,也可以绑定 slf4j 一起使用。推荐组合
slf4j + logback
。