23、springboot日志使用入门-- SLF4J+Logback 实现(springboot默认的日志实现),日志打印到控制台及日志输出到指定文件
作者:mmseoamin日期:2023-12-14

springboot日志使用入门

★ 典型的Spring Boot日志依赖:

 spring-boot-start.jar   
     -- spring-boot-starter-logging.jar (Spring Boot的日志包)
          -- logback(core、classic)
          -- log4j-to-slf4j.jar
          -- jul-to-slf4j.jar

就是springboot的默认的日志依赖实现。创建项目的时候存在这个依赖里面。

23、springboot日志使用入门-- SLF4J+Logback 实现(springboot默认的日志实现),日志打印到控制台及日志输出到指定文件,在这里插入图片描述,第1张

★ Java领域的日志框架可分为:

▲ 门面类(抽象层):SLF4J、JCL(Apache commons logging)、JBoss Logging
▲ 日志实现:Log4j、Log4j2、Logback、JUL(JDK内置的java.util.logging)
推荐应用程序面向日志门面编程,以便底层可以在不同的日志实现之间自由切换。
项目中的日志框架,通常是两个:日志门面(抽象)+ 日志实现

★ Spring Boot的日志设计

下面的日志实现就是基于 SLF4J+Logback

SLF4J+Logback:SLF4J是门面,Logback是实现

▲ Spring Boot日志采用如下组合:
- SLF4J+Logback:SLF4J是门面,Logback是实现
▲ 由于Spring Boot要整合大量其他框架,这些框架底层可能采用了各种不同的日志实现,
    因此Spring Boot需要将这些日志全部“路由”给SLF4J(把所有日志统一交给SLF4J来输出),
    以后开发者就只需要设置SLF4J的日志即可。
   因此还需要
   - log4j-to-slf4j.jar:它负责将Log4j日志路由到SLF4J。
   - jul-to-slf4j.jar:负责将JUL日志路由到SLF4J。
 【说明】:当你项目用了Spring Boot之后,Spring boot会负责将所有第三方框架日志都路由给SLF4J,
        开发者就只需要配置SLF4J日志,即可对所有的日志进行全盘控制。
 【注意】:将Spring Boot应用部署到服务器上,JUL生成的日志将不再路由到Spring Boot应用的日志。
         ——由于应用服务器底层往往都使用JUL日志,由于应用服务器本身、及服务器上可能部署了其他应用的日志
         这些日志当然与我们Spring Boot应用无关,所以Spring Boot默认不会将这些日志路由到SLF4J上。
 【总结】 Spring Boot统一了Java领域的所有框架所可能用到的日志实现,并将这些日志全部“路由”给SLF4J来管理,
          因此开发者只要管理SLF4J日志,即可对项目中所有日志框架进行管理。

★ 使用日志:

(1)在程序中获取Logger对象(org.slf4j包下的),通过LoggerFactory。
     也可用Lombok的@Slf4j注解来获取。
(2)在要输出日志的地方(相当于以前Systme.out.println)
     Logger的trace\debug\info\warn\error来输出不同级别的日志。

★ 日志级别

▲ 日志级别:
  
  TRACE < DEBUG < INFO < WARNING < ERROR
▲ 当日志输出方法的级别高于或等于应用日志的设置级别时,该日志才会实际输出。
   Spring Boot应用默认的日志级别是INFO,因此它默认只输出info、warn、error方法输出的日志。

★ 设置日志级别:

设置日志的级别,可通过以下方式:

▲ 改变Spring Boot的核心日志级别

  通过debug=true或trace=true等属性(通过配置文件、命令行参数、系统变量、OS环境变量等方式)
  改变整个Spring Boot核心的日志级别。

▲ 改变程序组件(包括所有各种框架)的核心日志级别

  通过logging.level.=属性(可通过配置文件、命令行参数、系统变量等方式)设置指定日志的日志级别。
 其中代表日志名,通常就是包名或全限定的类名,
  如果使用包名,那就意味着对该包下所有类统一设置日志级别。
  如果使用类名,那就意味着对该类设置日志级别。
而level则可以是trace、debug、info、warn和error等级别。

【小技巧】实际项目开发时,尽量避免使用System.out.println来做输出,而应该用日志来做输出。

System.out.println 在输出的时候,每打印一行都是需要进行IO的,所以会很耗性能。

如果你在调试时用了大量的System.out.println来做输出,到了项目上线时必须要删除这些输出语法,否则会因为IO造成性能影响。
但如果你用的日志(debug)来输出,项目上线时,只要将应用级别调高,这些日志输出就会被自动关闭,因此无需输出这些日志输出语句。
▲  互联网上常问如何控制日志输出
  Spring Boot让MyBatis输出它执行的SQL语句啊?非常简单:
   logging.level.=debug
   组件可以理解是类
  Spring Boot看到Redis的详细执行过程?非常简单:
   logging.level.io.lettuce.core=debug
   Spring Boot整合Redis默认使用Lettuce依赖,而io.lettuce.core就是Lettuce组件核心API所在的包。
  Spring Boot看到MongoDB的详细执行过程?非常简单:
   logging.level.com.mongodb=debug
  上面com.mongodb就是MongoDB核心API所在的包。
  由此可见,通过Spring Boot可以让它输出任意框架的执行过程,只需要如下设置
  logging.leve.<框架核心API所在的包>=debug

代码示例:

1、先创建一个类,获取日志对象。

2、然后在application.yml配置类里面配置一些日志信息—改变Spring Boot的核心日志级别

通过debug=true或trace=true等属性(通过配置文件、命令行参数、系统变量、OS环境变量等方式)改变整个Spring Boot核心的日志级别。

如图:这里在配置文件里面设置核心日志级别为 trace = true,就是级别为 trace。

但是打印出来的还是只有 info、warn 和error,但是控制台的启动记录里面还是有trace的,如图

23、springboot日志使用入门-- SLF4J+Logback 实现(springboot默认的日志实现),日志打印到控制台及日志输出到指定文件,在这里插入图片描述,第2张

这个是改变项目程序组件的核心日志级别,设置特定包下所有类的日志级别,打印的时候就可以如图,把 trace 和 debug 都打印出来

这个是让controller包下面的所有类的日志级别设置为 trace

23、springboot日志使用入门-- SLF4J+Logback 实现(springboot默认的日志实现),日志打印到控制台及日志输出到指定文件,在这里插入图片描述,第3张

这个是让LogController这个类的日志级别设置为 trace

23、springboot日志使用入门-- SLF4J+Logback 实现(springboot默认的日志实现),日志打印到控制台及日志输出到指定文件,在这里插入图片描述,第4张

★ 日志输出到文件:

Spring Boot默认只将日志输出到控制台,不输出到文件,如果要将日志输出到文件,
可为Spring Boot设置如下两个属性的其中之一:
- logging.file.name:设置日志文件的文件名。
- logging.file.path:设置日志文件的目录。使用默认的spring.log作为文件名。
logging.file.path 这个有一个好处,就是当日志文件过大的时候,就会自动把日志文件分成多个文件。

代码示例:

- logging.file.path:设置日志文件的目录。使用默认的spring.log作为文件名。

23、springboot日志使用入门-- SLF4J+Logback 实现(springboot默认的日志实现),日志打印到控制台及日志输出到指定文件,在这里插入图片描述,第5张

这个就是生成在文件夹中的日志文件,跟控制台的打印出来的是一样的。

23、springboot日志使用入门-- SLF4J+Logback 实现(springboot默认的日志实现),日志打印到控制台及日志输出到指定文件,在这里插入图片描述,第6张

Logback设置

logging.logback.rollingpolicy.file-name-pattern: 设置对日志归档的文件名模板
logging.logback.rollingpolicy.clean-history-on-start:设置应用启动时是否清除日志归档
logging.logback.rollingpolicy.max-file-size日志文件归档之前的最大大小
logging.logback.rollingpolicy.total-size-cap:日志归档在被删除之前所能容纳的最大大小
logging.logback.rollingpolicy.max-history: 保留多少天的日志归档(默认为7)
Java 的日志归档是指对生成的日志文件进行周期性或大小限制的管理,以便保留和存档旧的日志文件,以便后续的检查、分析和备份。
通常情况下,应用程序会生成大量的日志数据,这些日志文件会越来越大,占用系统存储空间。为了避免过多的日志文件影响系统性能和存储空间的占用,可以对日志进行归档管理。
具体来说,归档通常有以下几种方式:
基于时间的归档:按照一定的时间间隔(如每天、每周、每月)将日志文件进行归档,将旧的日志文件存档到特定的文件夹或压缩文件中,以便后续查阅。
基于大小的归档:当日志文件达到一定大小时,将当前的日志文件存档,然后重新创建一个新的日志文件,以确保日志文件的大小始终在一个可接受的范围内。

★ 日志组:

(1)将多个包定义一个组名,
(2)然后对整个组设置指定的日志级别
——这样即可将该组对应的所有包统一设置成相同的日志级别。
 日志组也是一个提高项目可维护性的小技巧。

就是一个项目有很多个包(文件夹),比如 controller,service、dao、domain、config 等等,然后我们想让controller、service、dao这三个包的日志级别设置为 debug 级别。但是又不可能在配置文件中一个包一个包的写配置,所以这个时候就可以用到日志组。

代码示例:

需求:我这个项目有三个包c1,c2,c3,我想让 c2 和 c3 这两个包的日志级别为 warn ,然后项目的其他包的日志级别为trace。

这里建3个包

23、springboot日志使用入门-- SLF4J+Logback 实现(springboot默认的日志实现),日志打印到控制台及日志输出到指定文件,在这里插入图片描述,第7张

我配置让 c2 c3这两个包的日志级别为warn

项目其他包的日志级别为 trace,其他包不可能一个一个写出来,所以直接把最大的包 boot 进行设置。

但是 c2 c3 这两个包又被包含在 boot 包里面,所以要看看c2 c3 这两个包的日志级别是我们要的 warn 级别,还是会因为被boot包 包含而变成trace级别

23、springboot日志使用入门-- SLF4J+Logback 实现(springboot默认的日志实现),日志打印到控制台及日志输出到指定文件,在这里插入图片描述,第8张

如图可以看出 c2 c3 这两个包的日志级别没有被 boot 包影响,还是我们要的warn级别。

而项目的其他包,如 c1 ,就是我们要的 trace 级别

23、springboot日志使用入门-- SLF4J+Logback 实现(springboot默认的日志实现),日志打印到控制台及日志输出到指定文件,在这里插入图片描述,第9张

这两个设置,谁放上面谁放下面都没有影响各自的日志级别,不会有那种放下面然后覆盖上面的情况。

23、springboot日志使用入门-- SLF4J+Logback 实现(springboot默认的日志实现),日志打印到控制台及日志输出到指定文件,在这里插入图片描述,第10张

上面的日志实现就是基于 SLF4J + Logback:SLF4J是门面,Logback是实现

▲ 门面类(抽象层):SLF4J、JCL(Apache commons logging)、JBoss Logging

▲ 日志实现:Log4j、Log4j2、Logback、JUL(JDK内置的java.util.logging)

★ 如何替换默认的日志实现(Logback)

▲  两步:
(1)去掉Logback依赖库,添加新日志实现的依赖库。
    Logback日志实现的优先级最高,当该日志实现的JAR存在时,Spring Boot总会使用该JAR包作为默认的日志实现。       
(2)在类加载路径的根路径下为新日志实现提供对应的配置文件。
     默认从类加载路径的根路径下加载日志配置文件,也可通过logging.config属性来设置新的加载路径。
     除了可根据底层依赖库自动选择日志实现外——根据JAR包来自动选择日志实现,找到哪个日志实现的JAR包,Spring Boot就是用哪个日志实现。
     还可通过org.springframework.boot.logging.LoggingSystem属性显式指定日志实现,
该属性的值可以是LoggingSystem实现类的全限定名。
▲  不同日志实现的配置文件:
Logback:logback-spring.xml、logback-spring.groovy、logback.xml或 logback.groovy
Log4j2: log4j2-spring.xml或log4j2.xml
JDK(JUL):logging.properties
Spring Boot 推荐 使用带-spring后缀的配置文件作为对应日志框架的配置文件。

★ 控制日志只输出到文件(不输出到控制台)

项目上线时比较实用!
 两步:
(1)控制日志输出到文件。
     指定logging.file.name或logging.file.path两个属性的其中之一。
(2)还需要显式提供日志实现对应的配置文件,通过该配置文件关闭日志在控制台的输出。
     ——这一步的配置文件往往应该是日志实现相关的,和Spring Boot关系并不大。

代码示例

1、创建一个 logback-spring.xml 配置文件,这个配置文件专门用来控制 logback 日志的,现在在这个配置文件进行配置,让日志不要输出到控制台,只输出到指定的文件就行

application.yml 的配置不需要改,还是那样。

23、springboot日志使用入门-- SLF4J+Logback 实现(springboot默认的日志实现),日志打印到控制台及日志输出到指定文件,在这里插入图片描述,第11张

启动项目,然后再访问方法,发现控制台都没有任何的日志输出,一片空白,然后打开日志输出的文件,发现成功只输出在文件中

如图:项目的启动时间是16:36分,文件中的日志也是同个时间,证明日志只输出在指定文件中,没有输出在控制台

23、springboot日志使用入门-- SLF4J+Logback 实现(springboot默认的日志实现),日志打印到控制台及日志输出到指定文件,在这里插入图片描述,第12张

logback-spring.xml配置文件


    
    
    
    
    
    
    
    
        
    

上面用的是默认的 Logback,现在要改成 log4j2

★ 通过例子示范使用log4j2替换Logback

 ——比较小众的应用场景。用的比较少,因为 springboot 推荐用 SLF4J+Logback ,所以没必要改成其他的
 但是这里可以尝试一下。
(1)去掉去掉Logback依赖库,添加Log4j2日志实现的依赖库。
(2)添加log4j2日志的配置文件——这一步是可选的。

代码示例

在创建项目的时候,就会默认有logback的日志依赖了,所以把这个logback的日志依赖从pom.xml文件中去除就可以了。

1、这个操作就是把springboot默认的日志排除在外(就是把logback排除在外)

2、添加新的日志实现

23、springboot日志使用入门-- SLF4J+Logback 实现(springboot默认的日志实现),日志打印到控制台及日志输出到指定文件,在这里插入图片描述,第13张

启动项目,发现日志输出和之前没有什么区别,因为更改日志实现,是底层实现的,不是具体的代码实现,可以理解为抽象的,所以用 logback 或者是 log4j2 ,只是底层实现方法变了,但是呈现出来的效果还是一样的。

如果:因为把logback 改成 log4j2 ,所以原本设置的 日志记录只输出到文件,不输出到控制台的作用,也失效了。

23、springboot日志使用入门-- SLF4J+Logback 实现(springboot默认的日志实现),日志打印到控制台及日志输出到指定文件,在这里插入图片描述,第14张

要看logback 和 log4j2 的区别,只能从maven 里面看了

23、springboot日志使用入门-- SLF4J+Logback 实现(springboot默认的日志实现),日志打印到控制台及日志输出到指定文件,在这里插入图片描述,第15张

改回来 logback ,原本设置的 日志记录只输出到文件,不输出到控制台的效果 就又恢复了

23、springboot日志使用入门-- SLF4J+Logback 实现(springboot默认的日志实现),日志打印到控制台及日志输出到指定文件,在这里插入图片描述,第16张

另一种日志打印方式:

在类上面添加注解 @Slf4j,那么就会有一个 log 对象,直接用 log.info 来打印日志就可以了。

@SpringBootApplication
@Slf4j
public class App {
    public static void main(String[] args) {
        var ctx = SpringApplication.run(App.class, args);
        //普通控制台打印
        System.err.println("普通打印myConfig01:"+ctx.getBean("myConfig01"));
        //@Slf4j 日志打印,输出info级别的日志,日志只能输出字符串
        //直接拿配置类这个bean,类名要小写
        log.info("日志打印myConfig01:"+ctx.getBean("myConfig01"));
        log.info("日志打印dataFormat:"+ctx.getBean("getDataFormat"));
    }

普通控制台打印和日志打印效果

23、springboot日志使用入门-- SLF4J+Logback 实现(springboot默认的日志实现),日志打印到控制台及日志输出到指定文件,在这里插入图片描述,第17张