【JavaEE进阶】——带你详细了解Spring日志以及配置日志

目录

🚩Spring日志的认识

🚩Spring日志的作用

🚩观察日志

🚩使用日志

🎈在程序中得到日志对象

🎈使⽤⽇志对象输出要打印的内容

🚩日志框架的介绍

[🎈门面模式(外观模式)](#🎈门面模式(外观模式))

👩🏻‍💻门面模式的实现

👩🏻‍💻门面模式的优点

🚩日志级别

🚩⽇志配置

🎈配置⽇志级别

🎈⽇志持久化

🎈日志分割

🎈修改日志格式

🎈更简单的⽇志输出

🚩总结


🚩Spring日志的认识

日志对于我们来说并不陌生,我们在学习javaee之前我们通过打印sout来观察程序的错误地方在哪里,而现在在spring的学习中,我们经常根据控制台的日志来分析和定位问题。
随着项⽬的复杂度提升, 我们对⽇志的打印也有了更⾼的需求, ⽽不仅仅是定位排查问题. ⽐如需要记录⼀些⽤⼾的操作记录(⼀些审计公司会要求), 也可能需要使⽤⽇志来记录⽤⼾的⼀些喜好,把⽇志持久化, 后续进⾏数据分析等. 但是 System.out.print 不能很好的满⾜我们的需求, 我们就需要使⽤⼀些专⻔⽇志框架(专业的事情交给专业的⼈去做)。

🚩Spring日志的作用

  • 1.定位和发现问题
  • 2.系统监控
  • 3.数据采集
  • 4.日志审记

🚩观察日志

Spring Boot 项⽬在启动的时候默认就有⽇志输出,如下图所⽰:

Spring帮我们集成了日志框架,我们可以直接使用即可。


🚩使用日志

打印⽇志的步骤:

  • • 在程序中得到⽇志对象.
  • • 使⽤⽇志对象输出要打印的内容

🎈在程序中得到日志对象

在程序中获取⽇志对象需要使⽤ ⽇志⼯⼚ LoggerFactory ,如下代码所⽰:

@RestController
public class LogsController {
    private Logger logger= LoggerFactory.getLogger(LogsController.class);
}

LoggerFactory.getLogger 需要传递⼀个参数, 标识这个⽇志的名称. 这样可以更清晰的知道是哪个类输出的⽇志. 当有问题时, 可以更⽅便直观的定位到问题类(可以像上述观察日志的时候样子一样,可以知道打印日志的类是哪个)
注意:Logger 对象是属于 org.slf4j 包下的, 不要导⼊错包.


🎈使⽤⽇志对象输出要打印的内容

LogsController类:

@PostConstruct 是 Java 中的一种注解,用于在依赖注入完成后执行初始化方法。它通常用于需要在依赖注入完成后进行一些初始化工作的场景。这个注解可以用在任何被管理的 bean(如 Spring 管理的 bean 或 Java EE 的 EJB 和 CDI bean)的方法上。

@RestController
public class LogsController {
    private Logger logger= LoggerFactory.getLogger(LogsController.class);
    @PostConstruct
    public void print(){
        logger.info("-----------打印日志内容--------------");
    }
}

运行结果:


🚩日志框架的介绍

slf4j并不是一个真实的日志实现,而是日志门面具体实现是log4j/logback等......


🎈门面模式(外观模式)

所谓门面模式,也称为外观模式,提供一个统一的接口,用来访问子系统的一段接口,其主要特征是定义了一个高层接口,让子系统更容易使用。

举个例子:我们进家门,我是一个比较怕黑的女生,我一进家门都是需要开灯的,等我一进门我需要先打开客厅的灯,然后打开厨房的灯,然后打开卧室的灯,一步一步的打开灯,然是如果形象化的理解门面模式,那就是我一进家门只用一个开关就打开了所有的灯,因为这个开关连接着各个灯的,所以这个开关就是提供的一个统一的接口,然后通过这个接口来访问系统的一段接口,方便了我们,也让子系统更容易的使用,不用我跑到厨房然后跑到卧室去开灯了,大大提升了开发效率,也简短了代码量。

⻔⾯模式主要包含2种⻆⾊:

  • 外观⻆⾊(Facade): 也称⻔⾯⻆⾊,系统对外的统⼀接⼝.
  • ⼦系统⻆⾊(SubSystem): 可以同时有⼀个或多个 SubSystem. 每个 SubSytem 都不是⼀个单独的类, ⽽是⼀个类的集合. SubSystem 并不知道 Facade 的存在, 对于 SubSystem ⽽⾔, Facade 只是另⼀个 客⼾端⽽已(即 Facade 对 SubSystem 透明)

(⽐如去医院看病,可能要去挂号, ⻔诊, 化验, 取药, 让患者或患者家属觉得很复杂, 如果有提供接待⼈员, 只让接待⼈员来处理, 就很⽅便)


👩🏻‍💻门面模式的实现

场景: 回家, 我们会开各个屋的灯. 离开家时, 会关闭各个屋的灯 ,如果家⾥设置⼀个总开关, 来控制整个屋的灯就会很⽅便. 我们使⽤⻔⾯模式的实现

门面角色(系统对外的统一接口)

@Controller
public class LightFacade {
    @Autowired
    private bedroomLightFracade bedroomLightFracade;
    @Autowired
    private LivingLightFacade livingLightFacade;
    @Autowired
    private kitchenLightFracade kitchenLightFracade;
    public void LightOn(){
        livingLightFacade.on();
        kitchenLightFracade.on();
        bedroomLightFracade.on();
    }
    public void LightOff(){
        livingLightFacade.off();
        kitchenLightFracade.off();
        bedroomLightFracade.off();
    }
}

接口实现开灯关灯的行为

每个子系统实行接口并完成开灯和关灯的操作

主逻辑(也就是客户端)客户端只用调用统一接口

客户端不用知道里面的其他类是什么,只需要通过调用统一接口中的方法,即可打开和关闭灯。

@Controller
public class FacadePatternDemo {
    @Autowired
    private  LightFacade lightFacade;
    public void light() {
        lightFacade.LightOn();
        lightFacade.LightOff();
    }
}

主程序中进行获取对象,并调用print方法

@SpringBootApplication
public class IocDemoApplication {
    public static void main(String[] args) {
        ApplicationContext context=SpringApplication.run(IocDemoApplication.class);
        LightFacade lightFacade=context.getBean(LightFacade.class);
        FacadePatternDemo facadePatternDemo=(FacadePatternDemo) context.getBean("facadePatternDemo");
       facadePatternDemo.light();
    }
}

👩🏻‍💻门面模式的优点

⻔⾯模式的优点

  • • 减少了系统的相互依赖. 实现了客⼾端与⼦系统的耦合关系, 这使得⼦系统的变化不会影响到调⽤它的客⼾端;
  • • 提⾼了灵活性, 简化了客⼾端对⼦系统的使⽤难度, 客⼾端⽆需关⼼⼦系统的具体实现⽅式, ⽽只需要和⻔⾯对象交互即可.
  • • 提⾼了安全性. 可以灵活设定访问权限, 不在⻔⾯对象中开通⽅法, 就⽆法访问

🚩日志级别

⽇志级别是开发⼈员⾃⼰设置的. 开发⼈员根据⾃⼰的理解来判断该信息的重要程度
类似公司管理, 通常由领导来判断什么样的事情需要汇报, 什么样的事情不需要汇报. 针对这些级别, Logger 对象分别提供了对应的⽅法, 来输出⽇志

@RestController
public class LogsController {
    private Logger logger= LoggerFactory.getLogger(LogsController.class);
    @PostConstruct
    public void print(){
        logger.info("-----------info--------------");
        logger.error("----------error-------------------");
        logger.debug("------------debug------------------");
        logger.warn("----------------warn-----------------");
        logger.trace("---------------trace-----------------");
    }
}

spring默认日志级别 :info
⽇志的输出级别默认是 info级别, 所以只会打印⼤于等于此级别的⽇志, 也就是info, warn和error. trace和debug级别都低于info,可以忽略不记。


🚩⽇志配置

上述是⽇志的使⽤, ⽇志框架⽀持我们更灵活的输出⽇志, 包括内容, 格式等。

🎈配置⽇志级别

⽇志级别配置只需要在配置⽂件中设置 "logging.level"配置项 即可,如下所⽰:

我们主要在yml配置文件中配置即可。

我们可以对日志进行分目录打印:比如Spring的日志只打印info,项目日志打印debug级别

logging:
  level:
    root: info #spring日志打印info级别
    com:
      example.ioc_demo:
        controller: debug    #项目日志打印debug级别

🎈⽇志持久化

以上的⽇志都是输出在控制台上的, 然⽽在线上环境中, 我们需要把⽇志保存下来, 以便出现问题之后追溯问题. 把⽇志保存下来就叫持久化。

⽇志持久化有两种⽅式

  • 1. 配置⽇志⽂件名
  • 2. 配置⽇志的存储⽬录

如果没有加路径,默认是放在当前项目下

配置⽇志⽂件的路径和⽂件名:

后⾯可以跟绝对路径或者相对路径
运⾏结果显⽰, ⽇志内容保存在了对应的⽬录下

logging:
  file:
   name: logger/springboot.log

配置⽇志⽂件的保存路径

logging:
  file:
    path: D:/temp


两种方式都存在(存在优先级)

logging:
  file:
    name: logger2/springboot.log
    path: D:/temp.log
  • name既可以设置路径,又可以设置名称
  • path只能设置路径,默认名称:spring.log
  • 如果两者同时存在,path就失效了,name的优先级要高于path

注意: logging.file.name 和 logging.file.path 两个都配置的情况下, 只⽣效其⼀, 以 logging.file.name 为准


🎈日志分割

如果我们的⽇志都放在⼀个⽂件中, 随着项⽬的运⾏, ⽇志⽂件会越来越⼤, 需要对⽇志⽂件进⾏分割.

当然, ⽇志框架也帮我们考虑到了这⼀点, 所以如果不进⾏配置, 就⾛⾃动配置
默认⽇志⽂件超过10M就进⾏分割

logging:
  file:
    name: logger2/springboot.log
  logback:
    rollingpolicy:
      max-file-size: 1KB
      file-name-pattern: ${LOG_FILE}.%d{yyyy-MM-dd}.%i

不是达到1KB就立刻进行分割的,以行来分割,不是以字符分割的。企业中,通常日志分割大小为200m或者500m或者xxx。

    1. ⽇志⽂件超过1KB就分割(设置1KB是为了更好展⽰. 企业开发通常设置为200M, 500M等, 此处没有明确标准)
    1. 分割后的⽇志⽂件名为:⽇志名.⽇期.索引

每次重启进程,那么就都会生成一个日志文件是1kb的,是按分割的1kb,不是按字符来分割的1kb.


🎈修改日志格式

⽬前 ⽇志打印的格式是默认的

日志配置文件修改(控制台日志,日志文件)

这也对应了下面我们所看见的默认格式。一一对应关系。


如果我们想要改一下控制台日志格式,我们需要配置。

  • 1.%clr(表达式){颜⾊} 设置输⼊⽇志的颜⾊ ,⽀持颜⾊有以下⼏种:

• blue
• cyan
• faint
• green
• magenta
• red
• yellow

    1. %d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd'T'HH:mm:ss.SSSXXX}} ⽇期和时间--精确到毫秒 %d{} ⽇期

${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd'T'HH:mm:ss.SSSXXX} ⾮空表达式, 获取
系统属性 LOG_DATEFORMAT_PATTERN , 若属性 LOG_DATEFORMAT_PATTERN 不存在,则使 ⽤ -yyyy-MM-dd HH:mm:ss.SSSXXX 格式, 系统属性可以System.getProperty("LOG_DATEFORMAT_PATTERN") 获取

    1. %5p 显⽰⽇志级别ERROR,MARN,INFO,DEBUG,TRACE.
    1. %t 线程名. %c 类的全限定名. %M method. %L 为⾏号. %thread 线程名称. %m 或者 %msg 显⽰输出消息. %n 换⾏符
    1. %5 若字符⻓度⼩于5,则右边⽤空格填充. %-5 若字符⻓度⼩于5,则左边⽤空格填充. %.15 若 字符⻓度超过15,截去多余字符. %15.15 若字符⻓度⼩于15,则右边⽤空格填充. 若字符⻓度超 过15,截去多余字符

🎈更简单的⽇志输出

每次都使⽤ LoggerFactory.getLogger(xxx.class) 很繁琐, 且每个类都添加⼀遍, lombok给我们提供了⼀种更简单的⽅式.

  • 1. 添加 lombok 框架⽀持
  • 2. 使⽤ @slf4j 注解输出⽇志

❗添加 lombok 依赖

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

❗输出⽇志

@Slf4j
@RestController
public class LogsController {
    public void log(){
        log.info("-----------info--------------");
    }
}

lombok提供的 @Slf4j 会帮我们提供⼀个⽇志对象 log, 我们直接使⽤就可以。

  • 在idea反编译的字节码中,我们就可以看到已经创建了logger对象,然后根据创建的对象调用info级别的日志。
  • 在源代码中用@Slf4j来帮助我们提供一个日志对象log,然后直接使用该log对象

🚩总结

常见的 Application Properties (配置文件官网)

  • ⽇志是程序中的重要组成部分,使⽤⽇志可以快速的发现和定位问题,Spring Boot 内容了⽇志框架,默认情况下使⽤的是 info ⽇志级别将⽇志输出到控制台的,我们可以通过 lombok 提供的 @Slf4j 注解和 log 对象快速的打印⾃定义⽇志.
  • ⽇志包含 6 个级别, ⽇志级别越⾼,收到的⽇志信息也就越少,我们可以通过配置⽇志的保存名称或保存⽬录来将⽇志持久化.

政治面貌:中共预备党员

相关推荐
乐之者v2 分钟前
leetCode43.字符串相乘
java·数据结构·算法
suweijie7683 小时前
SpringCloudAlibaba | Sentinel从基础到进阶
java·大数据·sentinel
公贵买其鹿4 小时前
List深拷贝后,数据还是被串改
java
xlsw_7 小时前
java全栈day20--Web后端实战(Mybatis基础2)
java·开发语言·mybatis
神仙别闹8 小时前
基于java的改良版超级玛丽小游戏
java
黄油饼卷咖喱鸡就味增汤拌孜然羊肉炒饭8 小时前
SpringBoot如何实现缓存预热?
java·spring boot·spring·缓存·程序员
暮湫9 小时前
泛型(2)
java
超爱吃士力架9 小时前
邀请逻辑
java·linux·后端
南宫生9 小时前
力扣-图论-17【算法学习day.67】
java·学习·算法·leetcode·图论
转码的小石9 小时前
12/21java基础
java