SpringBoot当中配置日志框架详解(保姆级教程)&日志框架的选择和使用

先简单聊聊日志框架

日志框架他在项目当中可以帮我们完成工作台输出、异步记录日志以及自动归档(把日志输出到文件)等功能。在框架的逐步成型当中,日志框架分为了抽象层和实现层。

所谓的抽象层,也可以称为统一接口层,在之前,我们都是代码当中直接实现接口层来完成日志处理,但是假如接口层发生变化,那么改动程度是非常大的,这也可以理解为代码的耦合性较高。

为降低代码耦合度,拆分成了两层,现在我们日志实现直接导入接口层和日志实现层相关jar包即可。基本上根本不用写什么代码即可快速实现日志处理。

框架选型

市场上存在非常多的日志框架。JUL(java.util.logging),JCL(Apache Commons Logging),Log4j,Log4j2,Logback、SLF4j、jboss-logging等。Spring Boot在框架内容部使用JCL,spring-boot-starter-logging采用了slf4j+logback的形式,Spring Boot也能自动适配(jul、log4j2、logback) 并简化配置

img

日志门面: SLF4J;
日志实现:Logback;

img

一般实现层都用用Logback,原因:JUL他相对来说没有其他的好,SLF4J和Log4j还有Logback是同一个人写的,并且Logback是Log4j的升级版。而Log4j2虽然也很完美,正是太完美,很多框架都没适配。

Slf4j的简单使用

在实际开发当中一般我们不会直接去掉实现类,而是去掉接口层的方法。

给系统里面导入slf4j的jar和 logback的实现jar,springboot当中spring-boot-starter-web本身就自带了,不需要导jar包

import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 
public class HelloWorld {
    
     
	public static void main(String[] args) {
    
    
		 private static final Logger logger = LoggerFactory.getLogger(HelloWorld.class); 
		 logger.info("Hello World"); 
	 } 
}

每一个日志的实现框架都有自己的配置文件。使用slf4j以后,配置文件还是做成日志实现框架自己本身的配置文

为什么要用static还有final呢?

  1. 定义成static final类型的变量,logger变量不可进行变更,第一次加载就加载到内存在中,读取速度快;
  2. static 修饰的变量是不管创建了new了多少个实例,也只创建一次,节省空间,如果每次都创建Logger的话比较浪费内存;final修饰表示不可更改常量,将域定义为static,每个类中只有一个这样的域.而每一个对象对于所有的实例域却都有自己的一份拷贝.,用static修饰既节约空间,效率也高。final 是本 logger 不能再指向其他 Logger 对象;
  3. 出于资源利用的考虑,LOGGER的构造方法参数是Class,决定了LOGGER是根据类的结构来进行区分日志,所以一个类只要一个LOGGER就可以了,故static。

SpringBoot当中配置步骤

1、排除其他框架日志包

一般项目当中我们一旦选择了一个日志实现框架之后,就会统一都用这个,在我们很多使用的框架当中都会自带日志框架,这个时候就需要排除包了,把他们自带的日志包排除掉,避免jar包冲突。

排除掉包不就报错了吗?
SLF4j给我们提供了中间包,这些中间包就是一个转换作用,将他原有的日志框架替换的基础上,并且保证框架能够正常运行。 这些替换包在引入spring-boot-starter-web的时候就已经加入了。这两个包的作用就是,将使用log4j和jul框架的,全都统一使用slf4j,所以我们需要做的就是将那些框架自带的jar包给排除掉。不让他引入。
在这里插入图片描述
pom示例:

<dependency>
	<groupId>org.apache.httpcomponents</groupId>
	<artifactId>httpclient-cache</artifactId>
	<!-- 依从 spring-boot 管理版本 -->
	<version>4.5.2</version>
	<scope>compile</scope>
	<exclusions>
		<exclusion>
			<!-- 使用 jcl-over-slf4j 代替 -->
			<groupId>commons-logging</groupId>
			<artifactId>commons-logging</artifactId>
		</exclusion>
	</exclusions>
</dependency>

2、了解默认配置

springboot自动装配当中会为我们配置好一些默认配置,即使我们使用日志框架,不做任何配置,他也是可以为我们完成一些基础功能的。

在这个jar包下,可以看出默认配置
在这里插入图片描述
在这里插入图片描述

从这里可以看出他的默认配置级别是info。

img

在默认情况下Spring Boot只会在控制台输出日志。
如果不用复杂的功能,只是希望能在文件中输出同样的日志。
只需要在application.properity加入如下配置:

#在当前磁盘的根路径下创建log文件夹和里面的MyProject文件夹;使用 spring.log 作为默认文件
logging.path=/log/MyProject

# 可以指定完整的路径;不指定磁盘路径在当前项目下生成springboot.log日志
logging.file=G:/springboot.log

#设置具体包的日志级别(这里将与MyBatis相关的mapper包设置为debug级别,效果就是在日志中输出sql语句)
logging.level.cn.gzl.Mapper=debug

日志输出格式:

%d表示日期时间,
%thread表示线程名,
%‐5level:级别从左显示5个字符宽度
%logger{50} 表示logger名字最长50个字符,否则按照句点分割。
%msg:日志消息,
%n是换行符

以上是日志输出格式标识符的含义:了解了其含义,我们就可以通过在全局配置当中添加配置,来修改出自己想要的控制台信息。

# 在控制台输出的日志的格式 
logging.pattern.console=%d{
    
    yyyy‐MM‐dd} [%thread] %5level %logger{
    
    50}%msg%n 
# 指定文件中日志输出的格式 
logging.pattern.file=%d{
    
    yyyy‐MM‐dd} === [%thread] === %5level === %logger{
    
    50} ==== %msg%n

4、指定配置文件

给类路径下放上每个日志框架自己的配置文件即可;SpringBoot就不使用他默认配置的了

img

logback.xml:直接就被日志框架识别了;
logback-spring.xml:日志框架就不直接加载日志的配置项,由SpringBoot解析日志配置,可以使用SpringBoot 的高级Profile功能

<springProfile name="staging"> 
	<!‐‐ configuration to be enabled when the "staging" profile is active ‐‐> 
	可以指定某段配置只在某个环境下生效 
</springProfile>

完整的logback-spring.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds">
    <include resource="org/springframework/boot/logging/logback/base.xml" />

	<!-- 日志文件名称 -->
	<contextName>spring-boot-log</contextName>
	<property name="log.path" value="c:/logback/logback.log" />

	<!-- 输出的控制台 -->
	<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
		<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
			<level>INFO</level>
		</filter>
		<encoder>
			<pattern>%d{
    
    HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{
    
    36} - %msg%n
			</pattern>
		</encoder>
	</appender>

	<!-- 输出到文件 -->
	<appender name="file"
		class="ch.qos.logback.core.rolling.RollingFileAppender">
		<!--日志名,用到了上面配置的路径-->
		<file>${
    
    log.path}</file>
		<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
			<fileNamePattern>${
    
    log.path}.%d{
    
    yyyy-MM-dd}.%i.log</fileNamePattern>
			<!-- 单个文件最大100M -->			
			<maxFileSize>100MB</maxFileSize>
			<!-- 保留30天的日志 -->
			<maxHistory>30</maxHistory>
		</rollingPolicy>

		<encoder>
			<pattern>%date %level [%thread] %logger{
    
    36} [%file : %line] %msg%n
			</pattern>
		</encoder>
	</appender>
	
	<!-- 开发环境 -->
	<springProfile name="dev">
		<logger name="com.gzl" level="INFO"/>
	</springProfile>
	
	<!-- 生产环境 -->
	<springProfile name="prod">
		<logger name="com.gzl" level="ERROR"/>
	</springProfile>

	
	<!-- 日志级别 -->
	<root level="error">
		<appender-ref ref="console" />
		<appender-ref ref="file" />
	</root>
	
	<root level="INFO">
		<appender-ref ref="console" />
		<appender-ref ref="file" />
	</root>
	
	<!--设置具体包的隔离级别,一般使用mybatis会单独设置mapper-->
    <logger name="com.gzl.cn.mapper.UserMapper" level="DEBUG"></logger>

 </configuration>

可以在application文件设置日志级别

spring.profiles.active=dev

为什么不能出现System.out.println()?

初学者一般在开发中或者调试bug的时候,都会习惯性的使用System.out.println语句,输出到控制台中,观察数据是否正常。开发或者调试完毕,很可能就忘记删除,直接就发布到生产中去了。

在这里插入图片描述
原理分析
在这里插入图片描述
从System.out.println的源代码,我们可以看到它在一开始就用synchronized同步锁给锁起来了,所以System.out.println是一个同步方法,在高并发的情况下,会严重影响性能。

总结

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



我们为啥要用日志?

最初我们开始接触 Java 的时候,我们通常会使用 System.out.println() 将我们想要知道的信息打印到控制台。
但是,如果在服务器上我们去运行我们的 Java 程序,这个时候就凸显了日志对于一个系统来说的重要性,查找异常信息、分析系统运行情况等都需要用到日志。

为什么是 SLF4J?

默认情况下,Spring Boot 会用 SLF4J + Logback 来记录日志,并用 INFO 级别输出到控制台。

SLF4J,即简单日志门面(Simple Logging Facade for Java),它可以看做是一个接口框架,并不提供具体的实现,具体的实现由类似于 Log4jLog4j2Logback 等等这样的日志框架去完成。

我们为什么要在实际的应用中去使用 SLF4J 的 API 呢?
在阿里巴巴的开发手册上也给我们明确【强制】规定了

img

而百度百科上也给出了相应的解释:

img

SLF4J 让你的代码独立于任何特定的日志记录 API,可以让我们的程序更加的健壮,不会让你因为不同日志的实现而导致的问题去分心。

使用 SLF4J 的另外一个理由就是,它可以支持占位符

String name = "Vi";
logger.debug("My Name is {}", name);

这段程序在运行时刻才会拿到 name这不仅缩减了代码中的许多字符串连接,而且减少了创建 String 对象所需要的堆内存资源

怎么使用 SLF4J?

如果我们在一个 Spring Boot 的程序中去使用 SLF4J,我们不需要去引入其他的包,因为我们引入的有关 spring-boot-starter 中就已经包含了有关 slf4j 的 jar 包。我们只需要通过 LoggerFactory 去获取即可:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
...
private static final Logger logger = LoggerFactory.getLogger(ResponseAop.class);

这里需要注意看我们选择的是不是 slf4j 包下的 Logger,不要选错了哟。

配合 Lombok 使用 @Slf4j

首先在 pom.xml 中添加 Lombok 的依赖:

        <dependency>
           <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

然后打开 IDEA 的设置项,在 Plugins 中查找:

img

img

注意安装插件后记得重启使其生效!

然后,我们在项目中就可以这样去使用:

@Slf4j
public class Slf4JTest {
    
    
    public static void main(String[] args) {
    
    
        log.info("This is a Slf4jTest");
    }
}

关于日志的配置

这里我就偷个懒,因为网上一搜一大堆,但是实际上你用的时候还是要根据自己的项目的情况进行使用的。

这里需要注意一点:默认情况下,Spring Boot 将日志输出到控制台,不会写到日志文件。如果要编写除控制台输出之外的日志文件,则需在 application.yml 中设置 logging.filelogging.path 属性。但是这俩属性同时配置的时候,只有 logging.file 生效!

猜你喜欢

转载自blog.csdn.net/qq_43842093/article/details/131024569