Spring - 7 ( 13000 字 Spring 入门级教程 )

一:Spring Boot 日志

1.1 日志概述

日志对我们来说并不陌生,我们可以通过打印日志来发现和定位问题, 或者根据日志来分析程序的运行过程,但随着项目的复杂度提升, 我们对日志的打印也有了更高的需求, 而不仅仅是定位排查问题

比如有时需要记录⼀些用户的喜好等等. 但是 System.out.print 不能很好的满足我们的需求, 此时我们就需要使用⼀些专门日志框架

1.2 日志的用途

通过前面的学习, 我们知道日志主要是为了发现问题, 分析问题, 定位问题的, 但除此之外, 日志还有很多用途

  1. 系统监控

我们可以通过日志记录这个系统的运行状态, 每⼀个方法的响应时间, 响应状态等, 对数据进行分析, 设置不同的规则, 超过阈值时进星报警,比如统计日志中关键字的数量,并在关键字数量达到⼀定条件时报警

  1. 数据采集

数据采集是⼀个比较大的范围, 采集的数据可以作用在很多方面, 比如数据统计, 推荐排序等,下图中的数据源, 其中⼀部分就来自于日志记录的数据.

在这里插入图片描述
3. 日志审计

通过系统日志分析,可以判断⼀些非法攻击, 非法调用,还可以解决系统处理过程中的安全隐患.

1.3 日志使用

Spring Boot 项目在启动的时候默认就有日志输出,如下图所示:

在这里插入图片描述

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

1.4 打印日志

打印日志的步骤:

  1. 在程序中得到日志对象.
  2. 使用日志对象输出要打印的内容

1.4.1 在程序中得到日志对象

在程序中获取日志对象需要使用日志工厂 LoggerFactory,如下代码所示:

private static Logger logger = LoggerFactory.getLogger(LoggerController.class);

LoggerFactory.getLogger 需要传递⼀个参数, 标识这个日志的名称. 这样可以更清晰的知道是哪个类输出的日志. 当有问题时, 可以更方便直观的定位到问题类

注意:Logger 对象是属于 org.slf4j 包下的, 不要导错包.

在这里插入图片描述

在这里插入图片描述

1.4.2 使用日志对象打印日志

日志对象的打印方法有很多种,我们可以先使用 info() 方法来输出日志,如下代码所示:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class LoggerController {private static Logger logger = LoggerFactory.getLogger(LoggerController.class);@RequestMapping("/logger")public String logger(){logger.info("--------------要输出日志的内容----------------");return "打印日志";}
}

这段代码的执行流程如下:

  1. 当请求到达 /logger 路径时,Spring框架会根据 @RequestMapping(“/logger”) 注解找到对应的处理方法 logger()。
  2. 接着 Spring 框架调用 logger 方法,该方法返回一个字符串 “打印日志”。
  3. 在 logger() 方法中,通过 LoggerFactory.getLogger(LoggerController.class) 获取了一个日志记录器对象 logger。
  4. 使用这个 logger 对象调用 info(),将日志消息--------------要输出日志的内容----------------"` 记录到日志中。
  5. 最后,方法返回字符串 “打印日志”,Spring 框架将其作为 HTTP 响应返回给客户端。

日志打印效果:

在这里插入图片描述

1.5 SLF4J 日志框架介绍

SLF4J 是门面模式的典型应用
在这里插入图片描述

SLF4J 不同于其他日志框架, 它不是⼀个真正的日志实现, 而是⼀个抽象层, 对日志框架制定的⼀种规范,所以 SLF4J 并不能独立使用, 需要和具体的日志框架配合使用.

1.6 门面模式

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

在这里插入图片描述

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

  • 外观角色:也称门面角色,系统对外的统一接口.
  • 子系统角色: 可以同时有⼀个或多个子系统.,每个子系统都不是⼀个单独的类,而是⼀个类的集合.,子系统并不知道门面角色的存在,对于子系统而言,门面角色只是另⼀个客户端而已,门面角色对子系统是透明的

举个例子:去医院看病可能要去挂号, 门诊, 化验, 取药, 这些流程可能会让患者或患者家属觉得很复杂, 但如果有提供接待人员, 只让接待人员来处理, 就变得很方便.

在这里插入图片描述

1.6.1 门面模式的实现

场景: 回家后我们会开各个屋的灯. 离开家时, 会关闭各个屋的灯,如果家里设置⼀个总开关, 来控制整个屋的灯就会很方便,我们使用门面模式的实现

public class FacadePatternDemo {public static void main(String[] args) {LightFacade lightFacade = new LightFacade();lightFacade.lightOn();}
}
/*** 灯的⻔⾯*/
class LightFacade{private Light livingRoomLight = new LivingRoomLight();private Light hallLight = new HallLight();private Light diningLight = new DiningLight();public void lightOn(){livingRoomLight.on();hallLight.on();diningLight.on();}public void lightOff(){livingRoomLight.off();hallLight.off();diningLight.off();}
}
interface Light {void on();void off();
}
/*** 客厅灯*/
class LivingRoomLight implements Light{@Overridepublic void on() {System.out.println("打开客厅灯");}@Overridepublic void off() {System.out.println("关闭客厅灯");}
}
/*** ⾛廊灯*/
class HallLight implements Light{@Overridepublic void on() {System.out.println("打开⾛廊灯");}@Overridepublic void off() {System.out.println("关闭⾛廊灯");}
}
/*** 餐厅灯*/
class DiningLight implements Light{@Overridepublic void on() {System.out.println("打开餐厅灯");}@Overridepublic void off() {System.out.println("关闭餐厅灯");}
}

门面模式的优点

  • 减少了系统的相互依赖. 实现了客户端与子系统的耦合关系, 这使得子系统的变化不会影响到调用它的客户端;
  • 提⾼了灵活性, 简化了客户端对子系统的使用难度, 客户端无需关心子系统的具体实现方式, 而只需要和门面对象交互即可.
  • 提高了安全性. 可以灵活设定访问权限, 不在门面对象中开通方法, 就无法访问

1.7 SLF4J 框架介绍

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

1.7.1 不引入日志门面

常见的日志框架有 log4J, logback 等. 如果⼀个项目已经使用了 log4j,而你还依赖另⼀个类库,假设这个类库是 Apache Active MQ, 它依赖于另外⼀个日志框架 logback, 那么你就需要把 logback 也加载进去.

在这里插入图片描述

存在问题:

  1. 不同日志框架的 API 接口和配置文件不同, 如果多个日志框架共存, 那么不得不维护多套配置文件
  2. 如果要更换日志框架, 应用程序将不得不修改代码, 并且修改过程中可能会存在⼀些代码冲突.
  3. 如果引如的第三方框架, 使用了多套, 那就不得不维护多套配置.

1.7.2 引入日志门面

引入门面日志框架之后, 应用程序只需要维护⼀套日志文件配置, 并且当底层实现框架改变时, 我们也不需要更改应用程序代码.

在这里插入图片描述

SLF4J 就是这个日志门面

1.8 日志格式的说明

我们之前打印的日志分别代表什么信息呢?

在这里插入图片描述
从上图可以看到,日志输出内容元素具体如下:

  1. 时间日期:精确到毫秒
  2. 日志级别:ERROR, WARN, INFO, DEBUG 或TRACE
  3. 进程ID
  4. 线程名
  5. Logger 名(通常使用源代码的类名)
  6. 日志内容

1.9 日志级别

日志级别代表着日志信息对应问题的严重性, 能够让我们更快的筛选符合目标的日志信息,日志的级别从高到低依次为: FATAL、ERROR、WARN、INFO、DEBUG、TRACE

  • FATAL: 致命信息,表示需要立即被处理的系统级错误.
  • ERROR: 错误信息, 级别较高的错误日志信息, 但仍然不影响系统的继续运行.
  • WARN: 警告信息, 不影响使用, 但需要注意的问题
  • INFO: 普通信息, 用于记录应用程序正常运行时的⼀些信息, 例如系统启动完成、请求处理完成等.
  • DEBUG: 调试信息, 需要调试时候的关键信息打印.
  • TRACE: 追踪信息, 比 DEBUG 更细粒度的信息事件(除非有特殊用意,否则请使用DEBUG 级别替代)

在这里插入图片描述

1.10 日志级别的使用

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

/*** 打印不同级别的⽇志* @return*/
@RequestMapping("/printLog")
public String printLog() {logger.trace("================= trace ===============");logger.debug("================= debug ===============");logger.info("================= info ===============");logger.warn("================= warn ===============");logger.error("================= error ===============");return "打印不同级别的⽇志" ;
}

观察打印的日志结果:

在这里插入图片描述

结果发现, 只打印了 info, warn 和 error 级别的日志,这与日志级别的配置有关, 日志的输出级别默认是 info 级别, 所以只会打印大于等于此级别的日志, 也就是 info, warn 和 error,fatal 就没必要打印了,因为是致命信息。

1.11 日志配置

1.11.1 配置日志级别

日志级别配置只需要在配置文件中设置 “logging.level” 配置项即可,如下所示:

  1. Properties 配置
logging.level.root: debug
  1. yml配置
logging:level:root: debug

properties 和 yml 只需要配置其中⼀个即可.

重新运行上述代码, 观察结果:

在这里插入图片描述

1.11.2 日志持久化

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

日志持久化有两种方式:

  1. 配置日志文件名
  2. 配置日志的存储目录

在这里插入图片描述

1.11.2.1 配置日志文件名
  1. Properties 配置
logging.file.name: logger/springboot.log
  1. yml 配置
# 设置⽇志⽂件的⽂件名
logging:file:name: logger/springboot.log

运行结果显示, 日志内容保存在了对应的目录下:

在这里插入图片描述

1.11.2.2 配置日志的存储目录
  1. Properties 配置
logging.file.path: D:/temp
  1. yml 配置
# 设置⽇志⽂件的⽬录
logging:file:path: D:/temp

运行程序, 该路径下多出⼀个日志⽂件: spring.log

在这里插入图片描述
注意: logging.file.name 和 logging.file.path 两个都配置的情况下, 只有 logging.file.name 生效

1.11. 3 配置日志文件分割

如果我们的日志都放在⼀个文件中, 随着项目的运行, 日志文件会越来越大, 需要对日志文件进行分割.(默认情况下日志文件超过 10M 就进行分割)

配置项说明默认值
logging.logback.rollingpolicy.file-name-pattern日志分割后的文件名格式${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz
logging.logback.rollingpolicy.max-file-size日志文件超过这个大小就自动分割10MB
  1. Properties 配置
logging.logback.rollingpolicy.file-name-pattern=${LOG_FILE}.%d{yyyy-MM-dd}.%i
logging.logback.rollingpolicy.max-file-size=1KB
  1. yml 配置
logging:logback:rollingpolicy:max-file-size: 1KBfile-name-pattern: ${LOG_FILE}.%d{yyyy-MM-dd}.%i
  1. 日志文件超过 1KB 就分割(设置 1KB 是为了更好展示. 企业开发通常设置为 200M, 500M 等)
  2. 分割后的日志文件名为: 日志名.日期.索引

项目运行, 多打印⼀些日志, 日志分割结果:
在这里插入图片描述

1.11.4 配置日志格式

目前日志打印的格式是默认的:

在这里插入图片描述

打印日志的格式, 也是支持配置的. 支持控制台和日志文件分别设置,配置日志格式我们通常使用 logging.pattern.console 和 logging.pattern.file 这两个配置项,下面我们来详细说说

1.11.4.1 logging.pattern.console

logging.pattern.console 用于控制台日志格式,它的默认值为:

%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}

第一个参数:

  1. %clr: 完整语法是:%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'T'HH:mm:ss.SSSXXX。这个模式中包含了以下元素:
      • yyyy: 年份,比如 2022、2023 等等。
      • MM: 月份,使用两位数表示,比如 01 表示一月,02 表示二月,以此类推。
      • dd: 日期,使用两位数表示,比如 01 表示一号,02 表示二号,以此类推。
      • 'T': 字符 ‘T’,可能用于表示日期和时间之间的分隔符。
      • HH: 小时,使用两位数表示,24 小时制,比如 00 表示午夜零点,01 表示凌晨一点,以此类推。
      • mm: 分钟,使用两位数表示,比如 00 表示整点,01 表示一分,以此类推。
      • ss: 秒,使用两位数表示,比如 00 表示整秒,01 表示一秒,以此类推。
      • SSS: 毫秒,使用三位数表示,比如 000 表示整毫秒,001 表示一毫秒,以此类推 - XXX: 时区偏移,表示与 UTC 时间的偏移量。例如,-07:00 表示比 UTC 时间晚七个小时的时区。

第二个参数:

  1. ${LOG_LEVEL_PATTERN:-%5p}: 这个部分是一个环境变量的占位符,用于指定日志级别的格式。如果环境变量 LOG_LEVEL_PATTERN 已经设置,那么就会使用它的值。如果没有设置,则使用默认值 %5p

    • ${LOG_LEVEL_PATTERN:-}: 这个部分表示一个环境变量的默认值的语法。在这种语法中,如果 LOG_LEVEL_PATTERN 环境变量存在,则将其值插入到这里;否则,使用默认值。

    • %5p: 这是日志级别的占位符。p 代表显示日志级别 ERROR,MARN,INFO,DEBUG,TRACE。数字 5 表示固定宽度格式化,即每个日志级别将占用 5 个字符的宽度。

例如,如果日志级别是 INFO,且使用 %5 的格式化,则输出将是 " INFO",以确保每行日志的日志级别部分对齐。这在查看日志时有助于提高可读性。

第三个参数:

  1. ${PID:- } 的含义是,如果环变量 PID 存在,则使用它的值作为进程ID;否则,使用空格替。这样设计的目的是在没有明确指定 PID 的情况下,使志保持整洁可读。

第四个参数:

这个参数 %clr(---){faint} 是一个用于设定日志输出样式和格式的表达式。

  1. ---:这是要显示的文本。在这种情况下,文本是三个连字符,可能用作日志中的分隔线或者标记。

第五个参数:

这个参数 %clr([%15.15t]){faint} 是一个用于设定日志输出样式和格式的表达式。

  1. [%15.15t]:15.15:这是时间戳格式化的规则,指了时间戳字符串的长度。在这种情况下,两个数字分别表示最小和最大的字符数限制。因此,15.15 意味着时间戳的长度被限制在15个字符。如果时间戳长度不足15个字符,则会在前面填充空格,如果超过15个字符会进行截断。

第六个参数:

这个参数 %clr(%-40.40logger{39}){cyan} 是用于设定日志输出样式和格式的表达式,

  1. (%-40.40logger{39}): 这部分指定日志消息的格式或布局。
    • -40.40: 这可能是一个指定字段宽度的格式说明符。这里的 -40 可能表示该字段的最小宽度为 40 个字符,40 可能表示最大宽度也为 40 个字符。这可以确保字段的对齐和格式整齐。
    • logger{39}: 这部分可能是在字段中指定要填充的内容。在这种情况下,logger 可能表示日志记录器的名称或标识符,而 {39} 则表示填充的内容是由长度为 39 的字符串表示的,即使日志记录器本身不到 39 个字符,通过填使其达到指定的宽度,可以确保日志输出的格式整齐,易于阅和理解。

第七个参数:

这个参数 %clr(:){faint} 是用于设定日志输出样式和格式的表达式,

  • %clr(:)(faint}:这部分主要用于设置日志输出中冒号的样式。

第八个参数:

%m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}这个参数是与日志记录相关的配置项

  • %m: 这个标记代表了日志消息。在日志中,通常会包含一条消息,用描述事件、错误或者其他需要记录的信息。m标记表示该位置被替换为日志消息。

  • %n: 这个标记代表了换行符,为了更好地阅读和解析

  • %w: 这个标记代表了异常信息。%w标记表示该位置将被替换为异常信息。

  • %Ex: 这个标记代表了异常的堆跟踪。,%Ex标记表示该位置将被替换为异常的堆栈跟踪信息。

  • LOG_EXCEPTION_CONVERSION_WORD: 这个部分表示一个环境变量的默认值的语法。在这种语法中,如果 LOG_EXCEPTION_CONVERSION_WORD 环境变量存在,则将其值插入到这里;否则,使用默认值。

1.11.4.2 logging.pattern.file

logging.pattern.file 用于控制日志文件的日志格式,它的默认值为:

%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{${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未定义,则默认使用yyyy-MM-dd'T'HH:mm:ss.SSSXXX格式。

  • y: 年份,表示年份的数字。例如,2024年将被表示为"2024"。

  • M: 月份,月份的数字。例如,4月份将被表示为"04"。

  • d: 日期,表示日期的数字。例如,29号将被表示为"29"。

  • 'T': 字符 ‘T’,它用于分隔日期和时间部分,通常在ISO 8601格式中使用。

  • H: 小时,表示小时的数字(24小时制)。例如,晚上11点将被表示为"23"。

  • m: 分钟,表示分钟的数字。例如,33分钟将被表示为"33"。

  • s: 秒,表示秒数的数字。例如,54秒将被表示为"54"。

  • S: 毫秒,表示毫秒数的数字。例如,123毫秒将表示为"123"。

  • X: 时区,表示时区的偏移量。例如,东八区北京时间)将被表示为"+08:00"。

第二个参数:

  • ${LOG_LEVEL_PATTERN:-%5p}: 这部分定义了日志级别格式。${LOG_LEVEL_PATTERN:-%5p}指定了日志级别的格式。如果环境变量LOG_PATTERN未定义,则默认使用%5p,它表示日志级别的最小宽度为5个字符,右对齐。

  • ${LOG_LEVEL_PATTERN}:这是一个环境变量,用于指定日志级别的输出格式

  • :-:这是一个默认值分隔符,用于指定当环境变量未设置时所采用的默认值。

  • %5p:这是实际的日志级别格式。

    • %p:这是日志级别的占位符。它会被替换为实际的日志级别。表示显示日志级别 ERROR,MARN,INFO,DEBUG,TRACE.

    • %5p:这表示日志级别的最小宽度为5个字符如果实际的日志级别的字符数少于5个,将会在左侧填充空格,使其达到5个字符宽度。如果超过个字符,则保持原样输出。

第三个参数:

${PID:- }--- [%t] : 用于定义日志记录中的进程ID、线程名。

  • ${PID:- }:这个部分定义了进程ID的输出格式。${PID}是一个环境变量,它表示进程ID。如果环境变量PID被设置了值(比如一个进程的实际ID),那么它将被替换为这个值;如果未设置,则会输出一个空格,这里的冒号:表示了进程ID结束的标志。

  • ---:这个部分是一个分隔符,用于分隔进程ID和线程名。

  • [%t]:这个部分定义了线程名的输出格式。%t是一个占位符,表示线程名。通常,线程名是指当前执行线程的名称。方括号[]用于包裹线程名,以区分它与其他日志信息。例如,[main]表示主线程。

第四个参数:

  • %-40.40logger{39}::这个部分定义了日志记录器名称的输出格式。

    • %-40: 这表示日志记录器名称的最小宽度为40个字符。如果日志记录器名称的长度不足40个字符,将会在右侧用空格填充,以达到40个字符的宽度。

    • .40: 这表示日志记录器名称的最大宽度为40个字符。如果日志记录器名称的长度超过40个字符,将会被截断,只保留前40个字符,并在末尾添加省略号以表示截断。

    • logger: 这是日志记录器名称的占位符。在实际的日志记录中,这个占位符会被替换为实际的日志记录器名称。

    • {39}:这部分指定了在无法确定日志记录器名称长度时显示的字符数。在这个例子中,如果日志记录器名称的长度无法确定,将会显示39个字符。

  • ::这个部分是一个隔符,用于分隔日志记录器名称和日志消息。

第五个参数:

  1. %m%n 这个参数是用来定义日志消息格式的

    • %m 是一个占位符,表示日志消息。在实际的日志记录中,这个占位符会被替换为实际的日志消息内容。

    • %n 是一个转义符,表示换行符。它用于在每条日志消息之后添加一个换行,以使日志输出更易读。

所以%m%n 保证了每条日志消息输出后都会有一个换行符。

  1. ${LOG_EXCEPTION_CONVERSION_WORD:-%wEx} 用来指定在记录日志时发生异常时如何转换异常信息的格式。这个参数可以分为两个部分来理解${LOG_EXCEPTION_CONVERSION_WORD}:-%wEx

    1. ${LOG_EXCEPTION_CONVERSION_WORD}:这部分是一个环境变量或者参数的引用,它表示如果 LOG_EXCEPTION_CONVERSION_WORD 这个环境变量被设置了,就使用其所指定的值;如果没有设置,就使用默认值。

    2. :-%wEx这部分是一个默认设定,如果环变量 LOG_EXCEPTION_CONVERSION_WORD 没有被设置,则使用该默认值。:- 表示如果环境变量没有设置,则采用后面的值。

现在让我们更详细地解释一下 %wEx 这个默认值的含义:

  • %w:这个占位符表示异常的引发位置(where)。在记录日志时,它会被替换为异常发生的位置信息,比如文件名、行号等。这可以帮助开发者追踪异常发生的具体位置,从而更容易地进行调试和排查问题。

  • E:这个占位符表示异常的类型(exception)。在记录日志时,它会被替换为异常的类型,比如错误的类型名或者错误代码。

  • x:这个占位符表示异常的详细信息(extra)。在记录日志时,它会被替换为异常的详细描述,通常包括异常的消息、堆栈跟踪等。

1.11.5 设置了颜色, 却没有生效的问题

此时我们需要配置, 让 idea 支持控制台颜色显示

  1. 打开启动配置, 添加 VM options

在这里插入图片描述

  1. 添加 VM options -Dspring.output.ansi.enabled=ALWAYS

在这里插入图片描述

  1. 重新启动程序, 就发现控制台支持颜色了

在这里插入图片描述

1.11.6 修改日志的默认格式

下面举一个简单的代码例子来修改日志的默认格式

  1. Properties 配置
logging.pattern.console='%d{yyyy-MM-dd HH:mm:ss.SSS} %c %M %L [%thread] %m%n'
  1. yml 配置
logging:pattern:console: '%d{yyyy-MM-dd HH:mm:ss.SSS} %c %M %L [%thread] %m%n'file: '%d{yyyy-MM-dd HH:mm:ss.SSS} %c %M %L [%thread] %m%n'
  • %d{yyyy-MM-dd HH:mm:ss.SSS}: 这是日期时间的格式化字符串,其中 %d 表示输出日期时间,{} 中的内容 yyyy-MM-dd HH:mm:ss.SSS 则规定了日期时间的显示格式为年-月-日 时:分:秒.毫秒。

  • %c: 这个标记代表了日志记录器(Logger)的名称。在日志中,Logger 通常用于标识记录日志的组件或类。

  • %M: 这个标记代表了调用日志记录器的方法名。它记录了日志记录发生的位置,即调用日志记录语句的方法名。

  • %L: 这个标记代表了日志记录发生的行号。它记录了日志记录语句在源代码中的行号。

  • [%thread]: 这个标记代表了线程名,用于记录日志记录发生时所处的线程。

  • %m: 这个标记代表了日志消息。它记录了需要被记录的具体信息。

  • %n: 这个标记代表了换行符。在日志中,为了更好地阅读和解析,通常会在不同的日志条目之间插入换行符。

项目运行, 观察日志变化:

在这里插入图片描述

通常情况下, 咱们就使用默认的日志格式打印即可.

1.11.7 更简单的日志输出

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

  1. 添加 lombok 框架支持
  2. 使⽤ @slf4j 注解输出日志。
1.11.7.1 添加 lombok 依赖
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional>
</dependency>
1.11.7.2 输出日志
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RestController;@Slf4j
@RestController
public class LogController {public void log(){log.info("--------------要输出⽇志的内容----------------");}
}

这段代码的执行流程如下:

  1. 导入库和注解

    • import lombok.extern.slf4j.Slf4j;: 导入 Lombok 的 @Slf4j 注解
    • import org.springframework.web.bind.annotation.RestController;: 导入 Spring Framework 的 @RestController 注解
  2. 类定义

    • @Slf4j: 这个注解告诉 Lombok 自动生成一个名为 log 的 Logger 对象,可以在类中直接使用。
    • @RestController: 用于处理 HTTP 请求并返回响应。
  3. 方法定义

    • log.info("--------------要输出⽇志的内容----------------");: 在 log 方法中调用 Logger 的 info 方法,输出一条信息到日志中。
  4. 执行流程

    • 当这个类被实例化,并且调用了 log() 方法时,会执行方法体内的代码。
    • log() 方法内部,使用了 log.info() 方法,表示以 INFO 级别记录一条日志信息。
    • 由于使用了 Lombok 的 @Slf4j 注解,因此无需手动创建 Logger 对象,可以直接使用 log 对象来记录日志。
    • 这条日志信息会根据日志配置的格式(如前面提到的 logging.pattern.consolelogging.pattern.file)被输出到相应的日志文件或控制台中。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/6764.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于JSP的酒店客房管理系统(二)

目录 第二章 相关技术介绍 2.1 Jsp的简介 2.2 sql server 2005 的简介 第三章 系统的分析与设计 3.1 系统需求分析 1&#xff0e;理解需求 2&#xff0e;需求分析 3.2开发及运行环境 3.3功能模块的设计 3.3.1 设计目标 3.3.2 客房管理系统前台的设计 3.3.3 操作员管…

nginxconfig.io项目nginx可视化配置--搭建-视频

项目地址 https://github.com/digitalocean/nginxconfig.io搭建视频 nginxconfig.io搭建 nginxconfig.io搭建 展示效果 找到这个项目需要的docker镜像&#xff0c;有项目需要的node的版本 docker pull node:20-alpine运行这个node容器,在主机中挂载一个文件夹到容器中 主机&a…

菜鸡学习netty源码(五)—— EventLoop

1.EventLoop的类关系图 2. EventExecutor /*** 返回自身的对象* Returns a reference to itself.*/OverrideEventExecutor next();/*** 获取所属的EventExecutorGroup* Return the {link EventExecutorGroup} which is the parent of this {link EventExecutor},*/EventExecuto…

利用大语言模型(KIMI)构建智能产品的信息模型

数字化的核心是数字化建模&#xff0c;为一个事物构建数字模型是一件非常繁杂和耗费人工的事情。利用大语言模型&#xff0c;能够轻松地生成设备的信息模型&#xff0c;我们的初步实验表明&#xff0c;只要提供足够的模板&#xff0c;就能够准确地生成设备的数字化模型。 我们尝…

Pytorch 实现 GAN 对抗网络

GAN 对抗网络 GAN&#xff08;Generative Adversarial Network&#xff09;对抗网络指的是神经网络中包括两个子网络&#xff0c;一个用于生成信息&#xff0c;一个用于验证信息。下面的例子是生成图片的对抗网络&#xff0c;一个网络用于生成图片&#xff0c;另一个网络用于验…

[C++基础学习-06]----C++指针详解

前言 指针是一个存储变量地址的变量&#xff0c;可以用来访问内存中的数据。在C中&#xff0c;指针是一种非常有用的数据类型&#xff0c;可以帮助我们在程序中对内存进行操作和管理。 正文 01-指针简介 指针的基本概念如下&#xff1a; 声明指针&#xff1a;使用“*”符…

[单片机课设]十字路口交通灯的设计

题目要求&#xff1a; 模拟交通灯运行情况。南北绿灯亮30秒&#xff0c;南北黄灯亮3秒&#xff0c;东西红灯亮33秒&#xff1b;南北红灯亮33秒&#xff0c;东西绿灯亮30秒&#xff0c;东西黄灯亮3秒&#xff1b;要求数码管同步显示时间的倒计时&#xff0c;用定时器实现延时。…

(HAL)STM32F103C8T6——内部flash模拟EEPROM

内部Flash大部分空间是用来存储烧录进单片机的程序代码&#xff0c;因此可以将非代码等无关区域用来存储数据。项目工程的代码量可以通过Keil uVision5软件底下框查看&#xff0c;如下图所示。一般只需参考代码量&#xff08;Code&#xff09;以及只读数据&#xff08;RO-data&…

某盾BLACKBOX逆向关键点

需要准备的东西&#xff1a; 1、原JS码 2、AST解混淆码 3、token(来源于JSON) 一、原JS码很好获取&#xff0c;每次页面刷新&#xff0c;混淆的代码都会变&#xff0c;这是正常&#xff0c;以下为部分代码 while (Qooo0) {switch (Qooo0) {case 110 14 - 55: {function O0…

C++入门第二节--关键字、命名空间、输入输出

点赞关注不迷路&#xff01;本节涉及c入门关键字、命名空间、输入输出... 1. C关键字 C总计63个关键字&#xff0c;C语言32个关键字 asmdoifreturntrycontinueautodoubleinlineshorttypedefforbooldynamic_castintsignedtypeidpublicbreakelselongsizeoftypenamethrowcaseen…

A Dexterous Hand-Arm Teleoperation System

A Dexterous Hand-Arm Teleoperation System Based on Hand Pose Estimation and Active Vision解读 摘要1. 简介2.相关工作2.1 机器人遥操作2.2 主动视觉&#xff08;Active Vision&#xff09; 3. 硬件设置4. 基于视觉的机器人手部姿态估计4.1 Transteleop4.2 Dataset 5. 主动…

升级OpenSSH版本(安装telnet远程管理主机)

一 OpenSSH是什么 OpenSSH 是 SSH &#xff08;Secure SHell&#xff09; 协议的免费开源实现。SSH协议族可以用来进行远程控制&#xff0c; 或在计算机之间传送文件。而实现此功能的传统方式&#xff0c;如telnet(终端仿真协议)、 rcp ftp、 rlogin、 rsh都是极为不安全的&…

C++奇迹之旅:string类接口详解(上)

文章目录 &#x1f4dd;为什么学习string类&#xff1f;&#x1f309; C语言中的字符串&#x1f309;string考察 &#x1f320;标准库中的string类&#x1f309;string类的常用接口说明&#x1f320;string类对象的常见构造 &#x1f6a9;总结 &#x1f4dd;为什么学习string类…

二维泊松方程(Neumann+Direchliet边界条件)有限元Matlab编程求解|程序源码+说明文本

专栏导读 作者简介&#xff1a;工学博士&#xff0c;高级工程师&#xff0c;专注于工业软件算法研究本文已收录于专栏&#xff1a;《有限元编程从入门到精通》本专栏旨在提供 1.以案例的形式讲解各类有限元问题的程序实现&#xff0c;并提供所有案例完整源码&#xff1b;2.单元…

stm32开发之netxduo网口通讯,网线热插拔处理

前言 在使用netxduo组件时&#xff0c;如果在上电过程中&#xff0c;未插入网线&#xff0c;eth驱动使能过程中未正常初始化本次使用以下几种方式进行设置 问题原因 使用定时器事件回调方式 网络组件中进行调整 /** Copyright (c) 2024-2024&#xff0c;shchl** SPDX-Licen…

Initialize failed: invalid dom.

项目场景&#xff1a; 在vue中使用Echarts出现的错误 问题描述 提示&#xff1a;这里描述项目中遇到的问题&#xff1a; 例如&#xff1a;在vue中使用Echarts出现的错误 ERROR Initialize failed: invalid dom.at Module.init (webpack-internal:///./node_modules/echarts…

Delta lake with Java--入门

最近在研究数据湖&#xff0c;虽然不知道研究成果是否可以用于工作&#xff0c;但我相信机会总是留给有准备的人。 数据湖尤其是最近提出的湖仓一体化概念&#xff0c;很少有相关的资料&#xff0c;目前开源的项目就三个&#xff0c;分别是hudi, delta lake, iceberg。最终选择…

算法打卡day41

今日任务&#xff1a; 1&#xff09;198.打家劫舍 2&#xff09;213.打家劫舍II 3&#xff09;337.打家劫舍III 4&#xff09;复习day16 198.打家劫舍 题目链接&#xff1a;198. 打家劫舍 - 力扣&#xff08;LeetCode&#xff09; 你是一个专业的小偷&#xff0c;计划偷窃沿街…

【hive】transform脚本

文档地址&#xff1a;https://cwiki.apache.org/confluence/display/Hive/LanguageManualTransform 一、介绍二、实现1.脚本上传到本地2.脚本上传到hdfs 三、几个需要注意的点1.脚本名不要写全路径2.using后面语句中&#xff0c;带不带"python"的问题3.py脚本Shebang…

LNMP部署wordpress

1.环境准备 总体架构介绍 序号类型名称外网地址内网地址软件02负载均衡服务器lb0110.0.0.5192.168.88.5nginx keepalived03负载均衡服务器lb0210.0.0.6192.168.88.6nginx keepalived04web服务器web0110.0.0.7192.168.88.7nginx05web服务器web0210.0.0.8192.168.88.8nginx06we…