当前位置:   article > 正文

Spring Boot日志

Spring Boot日志

目录

1 日志概述

2 日志使用

3 打印日志

3.1 在程序中得到日志对象

3.2 日志框架 

4 门面模式(外观模式)

4.1 门面模式的定义

4.2 门面模式的实现 

5 SLF4J框架

5.1 不引入日志门面

5.2 引入日志门面

6 日志介绍

6.1 日志格式

 6.2 日志级别

6.2.1 日志级别的分类

6.2.2 日志级别的使用

7 日志配置

7.1 日志级别的配置

7.2 日志持久化 

7.3 配置日志文件分割

7.4 设置日志颜色 

7.4.1 启动类设置

7.4.2 添加VM option

8 更简单的日志输出

8.1 添加lombok依赖

8.2 输出日志

总结

1 日志概述

从JavaSE部分到现在少不了日志,最初使用System.out.print来打印日志,通过打印日志来发现和定位问题,或者根据日志来分析程序的运行过程,在Spring的学习中,也经常根据控制台的日志来分析和定位问题,除此之外,日志还有更多的用途,比如系统监控和数据采集

2 日志使用

在SpringBoot项目启动的时候默认就有日志输出

我们通过System.out.print来打印日志 

  1. @RestController
  2. public class LoggerController {
  3. @PostConstruct
  4. public void logger() {
  5. System.out.println("打印日志");
  6. }
  7. }

 可以看到,通过System.out.print打印的日志,比SpringBoot打印的日志缺少很多信息

在SpringBoot中内置了日志框架Slf4j,可以直接在程序中调用Slf4j来输出日志

3 打印日志

打印日志的步骤:

1)在程序中得到日志对象

2)使用日志对象输出要打印的内容

3.1 在程序中得到日志对象

在程序中获取日志对象需要使用日志工厂LoggerFactory,这里需要选择slf4j这个接口

  1. @RestController
  2. public class LoggerController {
  3. private static Logger logger = LoggerFactory.getLogger(LoggerController.class);
  4. @PostConstruct
  5. public void logger() {
  6. logger.info("需要打印的日志");
  7. }
  8. }

3.2 日志框架 

SLF4J不同其他日志框架,它不是一个真正的日志框架实现,而是一个抽象层,对日志框架制定的一种规范,标准,接口,因此所有的SLF4J不能独立使用,需要和具体的日志框架配合使用

4 门面模式(外观模式)

SLF4J是门面模式的典型应用,但不仅仅使用了门面模式

4.1 门面模式的定义

门面模式(Facade Pattern)又称为外观模式,提供了一个统一的接口,用来访问子系统中的一群接口,其主要特征是定义了一个高层接口,让子系统更容易使用

门面模式主要包含2中角色:

1)外观角色(Facade):也称门面角色,系统对外的统一接口

2)子系统角色(SubSystem):可以同时有一个或者多个 SubSystem,每个SubSystem都不是一个单独的类,而是一个类的集合,SubSystem并不知道Facade的存在,对于SubSystem来说,Facade只是另一个客户端

例如:去医院看病,需要挂号、门诊、化验、取药,如果病人自己去办会很麻烦,但是如果由接待人员,让接待人员来处理,就会很方便

4.2 门面模式的实现 

场景:回到家我们会开每个房间的灯,离开家,会关闭房间的灯,如果在家里设置一个总开关,来控制整个家的灯会很方便,此时可以直接使用门面模式来实现

普通模式:

  1. public class Main {
  2. public static void main(String[] args) {
  3. LivingRoomLight livingRoomLight = new LivingRoomLight();
  4. livingRoomLight.on();
  5. HallLight hallLight = new HallLight();
  6. hallLight.on();
  7. DiningLight diningLight = new DiningLight();
  8. diningLight.on();
  9. }
  10. }
  11. interface Light {
  12. void on();
  13. void off();
  14. }
  15. /**
  16. * 客厅灯
  17. */
  18. class LivingRoomLight implements Light{
  19. @Override
  20. public void on() {
  21. System.out.println("打开客厅灯");
  22. }
  23. @Override
  24. public void off() {
  25. System.out.println("关闭客厅灯");
  26. }
  27. }
  28. /**
  29. * 走廊灯
  30. */
  31. class HallLight implements Light{
  32. @Override
  33. public void on() {
  34. System.out.println("打开走廊灯");
  35. }
  36. @Override
  37. public void off() {
  38. System.out.println("关闭走廊灯");
  39. }
  40. }
  41. /**
  42. * 餐厅灯
  43. */
  44. class DiningLight implements Light{
  45. @Override
  46. public void on() {
  47. System.out.println("打开餐厅灯");
  48. }
  49. @Override
  50. public void off() {
  51. System.out.println("关闭餐厅灯");
  52. }
  53. }

可以看出在普通模式中,我们需要一步一步的打开灯,这样就会有点麻烦,门面模式就可以帮我们解决这个问题

门面模式(外观模式)

  1. public class Main {
  2. public static void main(String[] args) {
  3. LightFacade lightFacade = new LightFacade();
  4. lightFacade.lightOn();
  5. }
  6. }
  7. /**
  8. * 灯的门面
  9. */
  10. class LightFacade {
  11. LivingRoomLight livingRoomLight = new LivingRoomLight();
  12. HallLight hallLight = new HallLight();
  13. DiningLight diningLight = new DiningLight();
  14. public void lightOn() {
  15. livingRoomLight.on();
  16. hallLight.on();
  17. diningLight.on();
  18. }
  19. public void lightOff() {
  20. livingRoomLight.off();
  21. hallLight.off();
  22. diningLight.off();
  23. }
  24. }
  25. interface Light {
  26. void on();
  27. void off();
  28. }
  29. /**
  30. * 客厅灯
  31. */
  32. class LivingRoomLight implements Light {
  33. @Override
  34. public void on() {
  35. System.out.println("打开客厅灯");
  36. }
  37. @Override
  38. public void off() {
  39. System.out.println("关闭客厅灯");
  40. }
  41. }
  42. /**
  43. * 走廊灯
  44. */
  45. class HallLight implements Light {
  46. @Override
  47. public void on() {
  48. System.out.println("打开走廊灯");
  49. }
  50. @Override
  51. public void off() {
  52. System.out.println("关闭走廊灯");
  53. }
  54. }
  55. /**
  56. * 餐厅灯
  57. */
  58. class DiningLight implements Light {
  59. @Override
  60. public void on() {
  61. System.out.println("打开餐厅灯");
  62. }
  63. @Override
  64. public void off() {
  65. System.out.println("关闭餐厅灯");
  66. }
  67. }

可以看出使用门面模式可以减少系统之间的相互依赖,使子系统的变化不会影响到调用它的客户端,从而降低了它们之间的耦合 

门面模式的优点:

1)减少系统的相互依赖,降低客户端和子系统之间的耦合,使子系统的变化不会影响到调用它的客户端

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

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

5 SLF4J框架

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

5.1 不引入日志门面

常见的日志框架由log4j,logback等,如果一个项目已经使用了log4j,而依赖的另一个库假如是Apache Active MQ,它依赖另一个日志框架logback,此时就需要把logback也加载进去

存在问题:

1)不同日志框架的API接口和配置文件不同,如果多个日志框架共存,就必须维护多套配置文件

2)如果要更换日志框架,应用程序将必须修改代码,并且修改过程中可能会存在一些冲突

3)如果引入第三方框架,使用了多套,就需要维护多套配置

5.2 引入日志门面

引入门面日志框架之后,应用程序和日志框架之间就有了统一的API接口,此时应用程序只需要维护一套日志文件配置,当底层实现框架改变时,不需要更改应用程序代码

SLF4J就是这个日志门面,SLF4J可以使代码独立于任意一个特定的日志API

6 日志介绍

6.1 日志格式

 6.2 日志级别

日志级别代表日志信息对应问题的严重性,为了更快的筛选符合目标的日志信息

6.2.1 日志级别的分类

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

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

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

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

INFO:普通信息,用于记录应用程序正常运行时的一些信息

DEBUG:调试信息

TRACE:追踪信息

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

6.2.2 日志级别的使用

日志级别是开发人员自己设置的,开发人员根据自己的理解来判断该信息的重要程度,针对这些级别,Logger对象分别提供了对应的方法,来输出日志

  1. @RestController
  2. public class LoggerController {
  3. private static Logger logger = LoggerFactory.getLogger(LoggerController.class);
  4. @PostConstruct
  5. public void logger() {
  6. logger.error("error日志");
  7. logger.warn("warn日志");
  8. logger.info("info日志");
  9. logger.debug("debug日志");
  10. logger.trace("trace日志");
  11. }
  12. }

可以看出只打印了erroe、warn、info级别的日志,这是因为日志的默认级别是info,所以只会打印大于等于此级别的日志 

7 日志配置

上述日志的使用,日志框架支持我们更灵活的输出日志,包括内容,格式等

7.1 日志级别的配置

  1. logging:
  2. level:
  3. root: debug

7.2 日志持久化 

以上的日志都是输出在控制台上的,在线上环境中,需要把日志保存下来,一遍出现问题之后追溯问题,把日志保存下来就叫持久化

日志持久化有两中方式

1)配置日志文件名

logging.file.name

2)配置日志的存储目录

logging.file.path

配置日志文件的路径和文件名

  1. logging:
  2. file:
  3. name: logger/springboot.log

后面可以跟绝对路径或者相对路径

此时日志内容就保存在对应的目录下 

配置日志文件的保存路径

  1. logging:
  2. file:
  3. path: E:/logger

这种方式只能设置日志的路径,文件名为固定的spring.log

注意:

logging.file.namelogging.file.path两个都配置的情况下只能生效一个,以logging.file.name为准

7.3 配置日志文件分割

如果日志都放在一个文件中,随着项目的运行,日志文件会越来越大,因此需要对日志文件进行分割,如果不进行配置的话,就会自动配置,默认日志文件超过10MB就进行分割

配置项说明默认值
logging.logback.rollingpolicy.fil
e-name-pattern
⽇志分割后的⽂件名
格式
${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz
logging.logback.rollingpolicy.m
ax-file-size
⽇志⽂件超过这个⼤
⼩就⾃动分割
10MB

配置文件分割:

  1. logging:
  2. file:
  3. path: E:/logger
  4. logback:
  5. rollingpolicy:
  6. max-file-size: 2KB
  7. file-name-pattern: ${LOG_FILE}.%d{yyyy-MM-dd}.%i

7.4 设置日志颜色 

7.4.1 启动类设置

7.4.2 添加VM option

启动控制台,观察颜色 

8 更简单的日志输出

每次使用LoggerFactory.getLogger(xxx.class)输出日志非常繁琐,并且每个类都要添加一遍,lombok给我们提供了一种更简单的方式

1)添加lombok框架支持

2)使用@slf4j注解输出日志

8.1 添加lombok依赖

  1. <dependency>
  2. <groupId>org.projectlombok</groupId>
  3. <artifactId>lombok</artifactId>
  4. <optional>true</optional>
  5. </dependency>

8.2 输出日志

  1. @Slf4j
  2. @RestController
  3. public class LoggerController {
  4. @PostConstruct
  5. public void logger() {
  6. log.error("error日志");
  7. log.warn("warn日志");
  8. log.info("info日志");
  9. log.debug("debug日志");
  10. log.trace("trace日志");
  11. }
  12. }

lombok提供的@Slf4j会帮我们提供一个日志对象log,直接使用即可 

总结 

1)日志是程序中的重要组成部分,使⽤日志可以快速的发现和定位问题,Spring Boot 提供了日志框架,默认情况下使用的是 info 日志级别将日志输出到控制台的,我们可以通过 lombok 提供的 @Slf4j 注解和 log 对象快速的打印自定义日志

2)日志包含6个级别,日志级别越高,收到的信息越少,可以通过配置日志的保存名称或者日志目录来将日志持久化

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/533427
推荐阅读
相关标签
  

闽ICP备14008679号