概述
以往的开发中,我们经常使用sout来打印一些信息,大量的使用System.out会增加资源的消耗,SpringBoot提供了一套日志系统,使用slf4j的logback来输出日志,效率高。
Logback和Log4j是同一个作者,Logback相比于Log4j,性能提高了10倍以上的性能,占用的内存也变小了,并且文档十分详细。
在《阿里巴巴Java开发手册(正式版)》中,日志规约一项第一条就强制要求使用 slf4j:
【强制】应用中不可直接使用日志系统(Log4j、Logback)中的API,而应依赖使用日志框架SLF4J中的API,使用门面模式的日志框架,有利于维护和各个类的日志处理方式统一。
强制”两个字体现出了 `slf4j`的优势,所以建议在实际项目中,使用 `slf4j`作为自己的日志框架。使用 `slf4j` 记录日志非常简单,直接使用 `LoggerFactory`创建即可。
Logback主要分为以下三个模块:
- logback-core:Logback的基础模块
- logback-classic:它是log4j的改良版本,同时它完整实现了Slf4j门面日志框架,可以很方便地更换成其它日志系统
- logback-access:访问模块与Servlet容器集成提供通过Http来访问日志的功能
SpringBoot内部已经集成了slf4j,我们在resource
目录下创建一个名为logback.xml
的文件。
日志级别按照从高到低依次为:TRACE < DEBUG < INFO < WARN < ERROR < FATAL,常用的有:DEBUG ,INFO ,WARN ,ERROR
开发时设置成trace方便定位问题,在生产环境上,将这个日志级别再设置成error级别即可。也可将这个日志级别设置成error
1. 使用slf4j记录日志
package logback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LogbackDemo {
private static Logger log = LoggerFactory.getLogger(LogbackDemo.class);
public static void main(String[] args) {
log.trace("======trace");
log.debug("======debug");
log.info("======info");
log.warn("======warn");
log.error("======error");
}
}
2.配置节点
<configuration> 标签是配置文件的根元素。
<root> 元素定义了根日志级别,它决定了所有日志消息的最低级别,此处设置为 INFO。根日志级别是一个过滤器,低于此级别的日志消息将被忽略。
<appender> 元素定义了不同的日志输出目标。上述配置文件中定义了两个 appender,分别是 STDOUT 和 FILE。每个 appender 都有一个 name 属性和 class 属性。STDOUT 是输出到控制台的 appender,FILE 是输出到文件的 appender。
<encoder> 元素定义了日志消息的格式。在上述配置中,STDOUT 和 FILE 都使用了相同的格式,包括时间戳、线程名、日志级别、日志记录器名称、消息文本等。你可以根据需要自定义日志消息的格式。
rollingPolicy 元素定义了日志文件的滚动策略。在 FILE appender 中,我们使用 TimeBasedRollingPolicy,它会根据时间滚动日志文件。例如,myapp.log 每天会滚动并保存为 myapp.2024-03-25.log,其中时间戳是当前日期。
2.1 配置configuration
根节点包含以下属性:
- scan:是否检测配置文件改变,重新加载配置,默认为true
- scanPeriod:扫描配置文件变化的时间间隔,如果没有给定时间单位,则默认为毫秒,如果仅仅设置了scan为true,则默认扫描间隔为1分钟
- debug:为true则打印logback的内部日志,默认为false
<configuration>
<?xml version="1.0" encoding="UTF-8"?>
<!-- scan : 当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true-->
<configuration scan="false" scanPeriod="60 seconds" debug="false">
</configuration>
2.2 子节点appender
负责写日志的组件,它有两个必要属性name和class。name指定appender名称,class指定appender的全限定名。
<appender>
2.3 完整的logback.xml示例
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<property name="LOG_PATTERN" value="%date{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n" />
<property name="FILE_PATH" value="D:/logs/course03/demo.%d{yyyy-MM-dd}.%i.log" />
<contextName>test</contextName>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${LOG_PATTERN}</pattern>
</encoder>
</appender>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 按照上面配置的FILE_PATH路径来保存日志 -->
<fileNamePattern>${FILE_PATH}</fileNamePattern>
<!-- 日志保存15天 -->
<maxHistory>15</maxHistory>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<!-- 单个日志文件的最大,超过则新建日志文件存储 -->
<maxFileSize>20MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder>
<!-- 按照上面配置的LOG_PATTERN来打印日志 -->
<pattern>${LOG_PATTERN}</pattern>
</encoder>
</appender>
<root level="DEBUG">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
</root>
<logger name="java.sql.PreparedStatement" level="DEBUG"/>
<logger name="org.apache.ibatis" level="DEBUG"/>
</configuration>
1. logger标签
<logger name=" " level=" " additivity=" " ></logger>
logger标签共有三个属性。
name: 必选,用来指定受此loger约束的某一个包或者具体的某一个类。
level: 用来设置打印级别(日志级别),大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,还有一个特俗值INHERITED或者同义词NULL,代表强制执行上级的级别。如果未设置此属性,那么当前loger将会继承上级的级别。
additivity: 是否向上级loger传递打印信息。默认是true。
<logger>可以包含零个或多个<appender-ref>元素,标识这个appender将会添加到这个logger。
2. root标签
<root level=" "></root>
root 标签只有一个level 属性,是logger的上级
level: 大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,不能设置为INHERITED或者同义词NULL。默认是DEBUG。
<root>可以包含零个或多个<appender-ref>元素,标识这个appender将会添加到这个root。
3. 日志输出规则
root和logger是父子的关系,logger的appender根据参数additivity决定是否要叠加root的appender,logger的级别是其自身定义的级别,和root的级别没什么关系。
首先找到这个类所在的logger(没有特别定义则默认为root),然后根据以上规则判断出这个logger的appender和level,就可以知道这个类的哪些日志会被输出到哪些地方了。
注意:任何一个类只会和一个logger对应,要么是定义的logger,要么是root,判断的关键在于找到这个logger,然后判断这个logger的appender和level。
3.logback.xml配置文件解析
logback.xml文件中主要用来做日志的相关配置,可以定义日志输出的格式、路径、控制台输出格式、文件大小、保存时长等
3.1 定义日志输出格式和存储路径
注意:日志存储的路径必须要是绝对路径
<configuration>
...
<property name="LOG_PATTERN" value="%date{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n" />
<property name="FILE_PATH" value="D:/logs/course03/demo.%d{yyyy-MM-dd}.%i.log" />
...
</configuration>
命名为“LOG_PATTER”,%date表示日期,%thread表示线程名,%-5level表示级别从左显示5个字符宽度,%logger{36}表示logger名字最长36个字符,%msg表
示日志信息,%n是换行符
然后再定义一下名为 “FILE_PATH” 文件路径,日志都会存储在该路径下。%i表示第i个文件,当日志文件达到指定大小时,会将日志生成到新的文件里,这里的i就
是文件索引,日志文件允许的大小可以设置,下面会讲解。这里需要注意的是,不管是 windows系统还是Linux系统,日志存储的路径必须要是绝对路径。
3.2 定义控制台输出
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<!-- 按照上面配置的LOG_PATTERN来打印日志 -->
<pattern>${LOG_PATTERN}</pattern>
</encoder>
</appender>
使用 <appender>
节点设置个控制台输出(class="ch.qos.logback.core.ConsoleAppender")
的配置,定义为 “CONSOLE”
。使用上面定义好的输出格式(LOG_PATTERN)
来输出,使用 ${}
引用进来即可。
3.3 定义日志文件的相关参数
<configuration>
<appender name="DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 按照上面配置的FILE_PATH路径来保存日志 -->
<fileNamePattern>${FILE_PATH}</fileNamePattern>
<!-- 日志保存15天 -->
<maxHistory>15</maxHistory>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<!-- 单个日志文件的最大,超过则新建日志文件存储 -->
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder>
<!-- 按照上面配置的LOG_PATTERN来打印日志 -->
<pattern>${LOG_PATTERN}</pattern>
</encoder>
</appender>
</configuration>
使用<appender>
定义一个名为 “FILE”
的文件配置,主要是配置日志文件保存的时间、单个日志文件存储的大小、以及文件保存的路径和日志的输出格式。
3.4 定义日志输出级别
<configuration>
<logger name="cn.hxzy.mapper" level="DEBUG" />
<root level="INFO">
<appender-ref ref="CONSOLE" />
<appender-ref ref="FILE" />
</root>
</configuration>
有了上面那些定义后,最后我们使用 来定义一下项目中默认的日志输出级别,这里定义级别为 INFO,然后针对 INFO级别的日志,使用 引用上面定义好的控制台日志输出和日志文件的参数。这样logback.xml文件中的配置就设置完了。
3.4 使用Logger在项目中打印日志
先写一个测试类
mport org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestContraller {
private final static Logger logger = LoggerFactory.getLogger(TestContraller.class);
@RequestMapping("/log")
public String testLog(){
log.debug("====测试日志debug级别打印====");
log.info("====测试日志info级别打印====");
log.warn("====测试日志warn级别打印====");
log.error("====测试日志error级别打印====");
return "success";
}
}
启动该项目,在浏览器中输入http://localhost:8080/log可以看到控制台的日志记录
4.注解 @Slf4j
4.1.注解由来
@Slf4j
是 Lombok提供的一种注解,用于在类中自动生成一个名为 log
的日志对象。通过使用 @Slf4j
注解,可以方便地在代码中使用日志功能,而无需手动创建和初始化日志对象。
4.2.注解示例
@Slf4j
public class MyClass {
// ...
}
在上述示例中,MyClass
类被标记为使用 @Slf4j
注解,它将自动创建一个名为 log
的日志对象
4.3.注解用法和注意事项
@Slf4j 注解可以用于类级别,用于为该类生成一个日志对象。
生成的日志对象 log 可以直接在代码中使用,例如调用 log.debug()、log.info() 等方法进行日志输出。
在使用 @Slf4j 注解之前,需要确保已正确配置了相关的日志实现库,例如 Logback 或者 Log4j。