Spring Boot使用slf4j进行日志记录

Spring Boot使用slf4j进行日志记录

背景

在开发中,我们经常使用System.out.println()来打印一些信息,但是这样不好,因为大量的使用会增加资源的消耗。我们实际项目中使用的是 slf4j 的 logback 来输出日志,效率挺高的,Spring Boot 提供了一套日志系统,logback 是最优的选择。当然了,除了选择logback,也可以选择log4j2或者log4j。
内容参考:武哥学编程

不建议System.out.println()来打印消息的原因

底层是System.out返回的对象是PrintStream,PrintStream调用out(),代码的内容是synchronized修饰的代码块。System.out.println()是一个同步方法,当多处调用System.out.println()的时候同步锁影响性能。


System// 返回的是静态的PrintStream。 
 public final static PrintStream out = null;



PrintStream...
   public void println() {
        newLine();
    }
 ...
     private void newLine() {
        try {
            // this指的是静态对象PrintStream 
            synchronized (this) {
                ensureOpen();
                textOut.newLine();
                textOut.flushBuffer();
                charOut.flushBuffer();
                if (autoFlush)
                    out.flush();
            }
        }
        catch (InterruptedIOException x) {
            Thread.currentThread().interrupt();
        }
        catch (IOException x) {
            trouble = true;
        }
    }

测试

public static void main(String[] args) {
    long start1 = System.currentTimeMillis();
    for(int i=0;i<100000;i++){
        System.out.println("i:"+i);
        }
    long end1 = System.currentTimeMillis();
    System.out.println("有输出语句的耗时:"+(end1-start1));
    long start2 = System.currentTimeMillis();
    for(int i=0;i<100000;i++){
        }
    long end2 = System.currentTimeMillis();
    System.out.println("无输出语句的耗时:"+(end2-start2));
}
 
有输出语句的耗时:408
无输出语句的耗时:0

强制

在日常开发或者调试的过程中,尽量使用log4j2或者logback这些异步的方法,进行日志的统一收集,禁止使用System.out.println。项目上线前也要进行全局搜索,防止有人误提交带有System.out.println的代码。

slf4j

1. slf4j 介绍

引用百度百科里的一段话:

SLF4J,即简单日志门面(Simple Logging Facade for Java),不是具体的日志解决方案,它只服务于各种各样的日志系统。按照官方的说法,SLF4J是一个用于日志系统的简单Facade,允许 最终用户在部署其应用时使用其所希望的日志系统。

这段的大概意思是:你只需要按统一的方式写记录日志的代码,而无需关心日志是通过哪个日志系统, 以什么风格输出的。因为它们取决于部署项目时绑定的日志系统。例如,在项目中使用了 slf4j 记录日志,并且绑定了 log4j(即导入相应的依赖),则日志会以 log4j 的风格输出;后期需要改为以 logback 的风格输出日志,只需要将 log4j 替换成 logback 即可,不用修改项目中的代码。这对于第三方组件的引入的不同日志系统来说几乎零学习成本,况且它的优点不仅仅这一个而已,还有简洁的占位符的使用 和日志级别的判断。
正因为 sfl4j 有如此多的优点,阿里巴巴已经将 slf4j 作为他们的日志框架了。在《阿里巴巴Java开发手册(正式版)》中,日志规约一项第一条就强制要求使用 slf4j:

  1. 【强制】应用中不可直接使用日志系统(Log4j、Logback)中的API,而应依赖使用日志框架SLF4J中的API,使用门面模式的日志框架,有利于维护和各个类的日志处理方式统一。

“强制”两个字体现出了 slf4j 的优势,所以建议在实际项目中,使用 slf4j 作为自己的日志框架。使用
slf4j 记录日志非常简单,直接使用 LoggerFactory 创建即可:

import  org.slf4j.Logger;  
import  org.slf4j.LoggerFactory;

public  class  Test  {
	private  static  final  Logger  logger  =  LoggerFactory.getLogger(Test.class);
// ……
}

小结- 重要-必看
  1. springboot框架默认的日志框架slf4j不能提供具体的日志实现,具体的日志实现是靠log4j、logback等日志框架;
  2. 阿里强制推荐使用slf4j日志的API。我理解为:可以把slf4j看作Java中的接口,log4j和logback可以看作它的实现类;我们在项目开发中调用的API均是slf4j的API,这些API都被log4j和logback都自己实现了;虽然log4j和logback都有自己的API,但是不推荐被使用,不被使用的原因是考虑到后期更改日志框架的时候修改的地方太大(比如:原先使用了log4j的A方法,现在日志框架改成了Logback可是logback没有A方法);
  3. springboot默认提供的slf4j是不会把信息打印到指定的文件中的,它只会在控制台打印信息。而log4j和logback有自己的xml配置文件,配置文件里面指定了输出日志的格式、日志文件名称、日志文件的位置等信息;
  4. 记住:slf4j是用LoggerFactory调用getLogger打印日志的。 上学的时候,自己搭建的项目使用的就是这种方式(公司也是使用这种方式),但是自己居然没有丝毫印象;这说明了自己当时只是实现了功能,并没有思考太多,日后必须对遇到的技术点做深入反思;

这是大学写的项目使用到了slf4j:
在这里插入图片描述

2. application.yml 中对日志的配置

Spring Boot 对 slf4j 支持的很好,内部已经集成了 slf4j,一般我们在使用的时候,会对slf4j 做一下配置。 application.yml 文件是 Spring Boot 中唯一一个需要配置的文件,一开始创建工程的时候是application.properties文件,个人比较喜欢用 yml 文件,因为 yml 文件的层次感特别好,看起来更直观,但是 yml 文件对格式要求比较高,比如英文冒号后面必须要有个空格,否则项目估计无法启动,而且也不报错。用 properties 还是 yml 视个人习惯而定,都可以。本课程使用 yml。
我们看一下 application.yml 文件中对日志的配置:

logging:
	config:  logback.xml 
	level:  
	  com.itcodai.course03.dao:  trace

logging.config 是用来指定项目启动的时候,读取哪个配置文件,这里指定的是日志配置文件是根
路径下的 logback.xml 文件,关于日志的相关配置信息,都放在 logback.xml 文件中了。
logging.level 是用来指定具体的 mapper 中日志的输出级别,上面的配置表示
com.itcodai.course03.dao 包下的所有 mapper 日志输出级别为 trace,会将操作数据库的 sql 打
印出来,开发时设置成 trace 方便定位问题,在生产环境上,将这个日志级别再设置成 error 级别即可
(本节课不讨论 mapper 层,在后面 Spring Boot 集成 MyBatis 时再详细讨论)。
常用的日志级别按照从高到低依次为:ERROR、WARN、INFO、DEBUG。

3. logback.xml 配置文件解析

在上面 application.yml 文件中,我们指定了日志配置文件 logback.xml , 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_PATTERN”,该格式中 %date 表示日
期, %thread 表示线程名, %-5level 表示级别从左显示5个字符宽度, %logger{36} 表示 logger 名
字最长36个字符, %msg 表示日志消息, %n 是换行符。

然后再定义一下名为 “FILE_PATH” 文件路径,日志都会存储在该路径下。 %i 表示第 i 个文件,当日志
文件达到指定大小时,会将日志生成到新的文件里,这里的 i 就是文件索引,日志文件允许的大小可以
设置,下面会讲解。这里需要注意的是,不管是 windows 系统还是 Linux 系统,日志存储的路径必须
要是绝对路径。

3.2 定义控制台输出
<configuration>
	<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
		<encoder>
			<!-- 按照上面配置的LOG_PATTERN来打印日志 -->
			<pattern>${LOG_PATTERN}</pattern>
		</encoder>
	</appender>
</configuration>

使用 节点设置个控制台输出( class=“ch.qos.logback.core.ConsoleAppender” )的
配置,定义为 “CONSOLE”。使用上面定义好的输出格式(LOG_PATTERN)来输出,使用 ${} 引用进
来即可。

3.3 定义日志文件的相关参数
<configuration>
	<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>10MB</maxFileSize>
			</timeBasedFileNamingAndTriggeringPolicy>
		</rollingPolicy>

		<encoder>
			<!--  按照上面配置的LOG_PATTERN来打印日志  -->
			<pattern>${LOG_PATTERN}</pattern>
		</encoder>
	</appender>
</configuration>

使用 定义一个名为 “FILE” 的文件配置,主要是配置日志文件保存的时间、单个日志文件
存储的大小、以及文件保存的路径和日志的输出格式。

3.4 定义日志输出级别
<configuration>
	<logger  name="com.itcodai.course03"  level="INFO"  />
	<root  level="INFO">
		<appender-ref  ref="CONSOLE"  />
		<appender-ref  ref="FILE"  />
	</root>
</configuration>

有了上面那些定义后,最后我们使用 来定义一下项目中默认的日志输出级别,这里定义级
别为 INFO,然后针对 INFO 级别的日志,使用 引用上面定义好的控制台日志输出和日志文件
的参数。这样 logback.xml 文件中的配置就设置完了。

4. 使用Logger在项目中打印日志

在代码中,我们一般使用 Logger 对象来打印出一些 log 信息,可以指定打印出的日志级别,也支持占
位符,很方便。

import  org.slf4j.Logger;  
import  org.slf4j.LoggerFactory;
import  org.springframework.web.bind.annotation.RequestMapping; 
import  org.springframework.web.bind.annotation.RestController;

@RestController 
@RequestMapping("/test") 
public  class  TestController  {

	private  final  static  Logger  logger  = LoggerFactory.getLogger(TestController.class);

	@RequestMapping("/log") 
	public  String  testLog()  {
		logger.debug("=====测试日志debug级别打印====");
		logger.info("======测试日志info级别打印====="); 
		logger.error("=====测试日志error级别打印===="); 
		logger.warn("======测试日志warn级别打印=====");

		// 可以使用占位符打印出一些参数信息
		String  str1  =  "123"; 
		String  str2  =  "456";
		logger.info("======str1:{};str2:{}",  str1,  str2);

		return  "success";
	}
}

启动该项目,在浏览器中输入 localhost:8080/test/log 后可以看到控制台的日志记录:

======测试日志info级别打印=====
=====测试日志error级别打印====
======测试日志warn级别打印=====

因为 INFO 级别比 DEBUG 级别高,所以 debug 这条没有打印出来,如果将 logback.xml 中的日志级别
设置成 DEBUG,那么四条语句都会打印出来,这个大家自己去测试了。同时可以打开
D:\logs\course03\ 目录,里面有刚刚项目启动,以后后面生成的所有日志记录。在项目部署后,我们
大部分都是通过查看日志文件来定位问题.

5.扩展

场景:
公司项目是多模块的Maven项目,打算把不同模块的日志各自输出到不同的日志文件。
在这里插入图片描述
提示:
关注一下两个标签:和。

6. 总结

本节课主要对 slf4j 做了一个简单的介绍,并且对 Spring Boot 中如何使用 slf4j 输出日志做了详细的说
明,着重分析了 logback.xml 文件中对日志相关信息的配置,包括日志的不同级别。最后针对这些配
置,在代码中使用 Logger 打印出一些进行测试。在实际项目中,这些日志都是排查问题的过程中非常
重要的资料

Spring使用 SLF4J 和 Log4j2,需要在 Gradle 中添加以下依赖: ``` dependencies { implementation 'org.springframework.boot:spring-boot-starter' implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-log4j2' implementation 'org.slf4j:slf4j-api:1.7.30' implementation 'org.slf4j:jul-to-slf4j:1.7.30' implementation 'org.slf4j:log4j-over-slf4j:1.7.30' implementation 'org.apache.logging.log4j:log4j-core:2.14.1' implementation 'org.apache.logging.log4j:log4j-slf4j-impl:2.14.1' } ``` 其中,`spring-boot-starter-log4j2` 包含了 Log4j2 的依赖,`slf4j-api` 是 SLF4J 的接口,`jul-to-slf4j` 和 `log4j-over-slf4j` 是将 JUL 和 Log4j 转换为 SLF4J 的实现,`log4j-core` 和 `log4j-slf4j-impl` 是 Log4j2 的实现。 在 Spring 中配置 Log4j2,需要在 `src/main/resources` 目录下创建一个 `log4j2.xml` 文件,配置如下: ``` <?xml version="1.0" encoding="UTF-8"?> <Configuration status="WARN"> <Appenders> <Console name="Console" target="SYSTEM_OUT"> <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/> </Console> </Appenders> <Loggers> <Root level="info"> <AppenderRef ref="Console"/> </Root> </Loggers> </Configuration> ``` 这里使用了一个控制台日志输出的 Appender,配置了日志输出的格式和级别。最后将 Appender 添加到 Root Logger 中即可。 在 Spring使用日志,可以直接使用 SLF4J 的接口,例如: ``` import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class MyClass { private static final Logger logger = LoggerFactory.getLogger(MyClass.class); public void myMethod() { logger.debug("Debug message"); logger.info("Info message"); logger.warn("Warn message"); logger.error("Error message"); } } ``` 这里使用了 `LoggerFactory.getLogger` 方法创建了一个 Logger 实例,然后使用不同级别的日志输出信息。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@来杯咖啡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值