SpringBoot日志

(一).使用日志

1.打印日志

在SpringBoot项目中,启动项目的时候,默认就是有日志进行输出的

可以看到,上图就是SpringBoot打印的日志。

之前我们打日志都是通过**"System.out.println()"**的方式进行打日志

可以发现,我们手动打印的日志,相对于SpringBoot打印的日志,好像缺了不少的东西,这是因为SpringBoot内置了Slf4j日志框架,同样,我们也可以使用Slf4j来进行打日志。

可以看到,我们输入"Logger"的时候,出现了6个接口或类,这个一会再进行介绍,先使用。

java 复制代码
package org.com.spring_log.blog.spring_log_blog.controller;


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

@RequestMapping("logger")
@RestController
public class LoggerController {

    //定义对象                                           //如果括号中跟的是类名,则日志中显示的是"全限定类名"(路径+类名)
    private static Logger logger= LoggerFactory.getLogger(LoggerController.class);  //如果跟的是字符串的话,则日志中显示的是字符串

    @RequestMapping("/print")
    public String print(){
        System.out.println("打印日志");
        logger.info("logger打印对象");
        return "打印日志";
    }
}

2.介绍日志框架

可以看到,我只输入了一个Logger,就出现了六个同名称的类或接口,下面就介绍一下划线的这几个。

事实上,Slf4j不同于其他日志框架,它并不是一个真正的日志实现,它只是对日志框架指定了一种规范。所有Slf4j并不能独立使用,需要和具体的日志框架配合使用。

(1).介绍"门面模式"

门面模式,又称为"外观模式",提供了一个统一的接口,用于访问子系统中的一群接口,其主要特征就是定义了一个高层接口,让子系统更容易使用。Slf4j是门面模式的典型应用。

门面模式包含了两种角色:

外观角色:也称门面角色,系统对外的统一接口,例如Slf4j

子系统角色:可以同时有一个或多个子系统角色。每个子系统角色都不是一个单独的类,而是一个类的集合,例如,log4j 1/2 JUL logback。子系统角色并不知道外观角色的存在,对于子系统角色来说,外观角色只是另一个客户端而已

可以理解为,我们使用Slf4j打印日志的时候,事实上,Slf4j又调用了logback的接口,来实现的日志的打印。对于Slf4j来说,他只是调用了具体框架的接口。站在logback的视角,他只知道有东西调用了它的接口,并不知道是Slf4j,所以对于logback来说,Slf4j只不过是一个客户端

(2).门面模式的实现

场景:我们回到家后,都会开各个屋的灯,离开家的时候,又会关闭各个屋的灯。那么就可以设置一个总开关,来控制整个屋的灯。这就是典型的"门面模式"的实现

主方法

java 复制代码
package org.com.log_demo.spring_log_demo.facade;

public class Main {

    public static void main(String[] args) {
        FacadeClient facadeClient=new FacadeClient();
        facadeClient.open();
        facadeClient.close();
    }
}

灯接口

java 复制代码
package org.com.log_demo.spring_log_demo.facade;

public interface Light {
    public abstract void open();
    public abstract void close();
}

主开关

java 复制代码
package org.com.log_demo.spring_log_demo.facade;

public class FacadeClient implements Light{

    private BadRoom badRoom=new BadRoom();
    private LivingRoom livingRoom=new LivingRoom();

    @Override
    public void open() {
        badRoom.open();
        livingRoom.open();
    }

    @Override
    public void close() {
        badRoom.close();
        livingRoom.close();
    }
}

卧室灯

java 复制代码
package org.com.log_demo.spring_log_demo.facade;

public class BadRoom implements Light{
    @Override
    public void open() {
        System.out.println("打开卧室灯");
    }

    @Override
    public void close() {
        System.out.println("关闭卧室灯");
    }
}

客厅灯

java 复制代码
package org.com.log_demo.spring_log_demo.facade;

public class LivingRoom implements Light{
    @Override
    public void open() {
        System.out.println("打开客厅灯");
    }

    @Override
    public void close() {
        System.out.println("关闭客厅灯");
    }
}

程序运行结果

(3)."门面模式"的优点

①.减少了系统的相互依赖,实现了客户端与子系统的耦合关系。使得子系统的变化不会影响到调用它的客户端。

②.提高了灵活性,简化了客户端对子系统的使用难度,客户端无需关心子系统的具体实现方式,只需要和门面对象交互即可。

③.提高了安全性,可以灵活设定访问权限,不在门面对象中开通方法,就无法访问

(4).Slf4j具体介绍

Slf4j是其他日志框架的门面。可以理解为提供日志服务的统一API接口,并不涉及到具体的日志实现。

当我们不引入日志门面的时候

如果一个项目中使用了log4j,而你依赖的是另一个库,例如logback,那么就需要把logback也加载进去。但是这样就会出现问题,具体如下:①.不同日志框架的api接口和配置文件不同,如果想要多个日志框架共存,那么就需要维护多套配置文件 。②.如果要更换日志框架,应用程序就不得不修改代码,并且修改的而过程中可能会存在一些代码冲突 。③.乳沟引入了第三方框架,使用了多态,那么就不得不维护多套配置

当我们引入日志门面的时候

这个Slf4j就是"日志门面"。Slf4j会使代码独立于任意一个特定的日志API。

(二).日志的格式说明

关于SpringBoot的日志格式,以及每一部分的作用,展开具体解释。

(三).日志的级别

1.日志级别的分类

日志级别从高到低依次为:FATAL,ERROR,WARN,INFO,DEBUG,TRACE

级别越高,收到的消息越少

FATAL:致命信息,表示需要立即被处理的系统级错误

ERROR:错误信息,级别较高的错误日志信息,但仍然不影响系统的继续运行。

WARN:警告信息,不影响使用,但需要注意的问题

INFO:普通信息,用于记录应用程序正常运行的一些信息,例如系统启动完成

DEBUG:调试信息,需要调试时候的关键信息

TRACE:追踪信息,比DEBUG更细粒度的信息事件(除⾮有特殊⽤意,否则使⽤DEBUG级别替代)

2.日志级别的使用

java 复制代码
package org.com.spring_log.blog.spring_log_blog.controller;


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

@RequestMapping("logger")
@RestController
public class LoggerController {

    //定义对象                                           //如果括号中跟的是类名,则日志中显示的是"全限定类名"(路径+类名)
    private static Logger logger= LoggerFactory.getLogger(LoggerController.class);  //如果跟的是字符串的话,则日志中显示的是字符串

    @RequestMapping("/print")
    public String print(){
        logger.trace("logger trace");
        logger.debug("logger debug");
        logger.info("logger info");
        logger.warn("logger warn");
        logger.error("logger error");
        return "打印日志";
    }
}

可以看到,日志级别的打印基本都出来了,但是没有trace级别 和 debug 级别 和 fatal 级别,这是因为SpringBoot默认的日志框架是LogBack,LogBack没有fatal 级别,他被映射到了error级别。关于为什么没有trace级别和debug级别,是因为SpringBoot的默认日志输出级别为info,所以只会打印大于等于info级别的日志

(四).日志的配置

1.配置日志级别

java 复制代码
#设置日志级别
logging:
  level:
    root: info
    org:
      com:
        spring_log:
          blog:
            spring_log_blog:
              controller: trace
#root目录表示 "根目录",将"根目录"的日志级别是设置为"info",将"org.com.spring_log.blog.spring_log_blog.controller"的日志级别设置为"trace"

可以看到,五个日志级别都打印出来了

2.日志持久化

日志持久化,是为了之后出现问题然后通过日志来追溯问题来设计的,简单的来说就是把日志保存下来,就叫持久化。在这里,既可以配置日志文件名,也可以配置日志的存储目录

java 复制代码
logging:
  file:
    name: log/log.log   #name属性,可以配置路径,也可以配置名称
    path: logger/       #path属性,只能配置路径,默认文件名为"spring.log",并且文件名不能修改

可以看到,我们的日志就保存下来了

3.配置日志文件分割

日志文件分割,指的就是,随着程序的不断运行,日志会越来越多,此时,为了避免日志文件过大,可以对日志文件进行分割。默认⽇志⽂件超过10M就进⾏分割

java 复制代码
logging:
  logback:
    rollingpolicy:
      max-file-size: 1KB      #修改分割文件的大小,一旦生成的日志文件超过1KB,则就会进行分割
      file-name-pattern: ${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz   #配置日志文件的名称

注意:假设说现在产生了一条日志,但是当往日志文件中写的时候,写了一半,日志文件满了,此时,即使日志文件满了,Spring也会将这条日志写完

4.配置日志格式

这个事实上不作为重点,只稍微介绍一下

java 复制代码
#配置日志格式
  pattern:
    console:          #设置控制台日志格式
    file:             #设置文件的日志格式

%clr(%d{{LOG_DATEFORMAT_PATTERN:-yyyy-MM dd'T'HH:mm:ss.SSSXXX}}){faint} %clr({LOG_LEVEL_PATTERN:-
%5p}) %clr({PID:- }){magenta} %clr(---){faint} %clr(\[%15.15t\]) {faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n{LOG_EXCEPTION_CONVERSION_WORD:-%wEx}
这是控制台的日志格式默认值
%d{{LOG_DATEFORMAT_PATTERN:-yyyy-MM dd'T'HH:mm:ss.SSSXXX}} {LOG_LEVEL_PATTERN:-%5p} {PID:- } --- \[%t\] %-40.40logger{39} : %m%n{LOG_EXCEPTION_CONVERSION_WORD:-%wEx}
这是文件的日志格式默认值

%d表示"日期",%clr(表达式){颜色} 表示"设置输入日志的颜色",%5p表示"日志级别",%t表示"线程名",%c表示"类的全限定名",%M表示"method",%L表示"行号",%thread表示"线程名称",%m或者%msg表示"输出消息",%n表示"换行符"

(五).使用注解

我们可以通过添加lombok依赖,然后使用注解的方式来简化我们创建日志对象的步骤

1.添加依赖

XML 复制代码
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

2.输出日志

java 复制代码
package org.com.spring_log.blog.spring_log_blog.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Slf4j   //@Slf4j 会自动帮助我们生成一个 "log" 对象
@RequestMapping("/logger2")
@RestController
public class LoggerController2 {

    @RequestMapping("/print2")
    public String print(){
        log.error("error");
        log.warn("warn");
        log.info("info");
        log.debug("debug");
        log.trace("trace");
        return "打印日志";
    }
}