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{
    @Override
    public void on() {
        System.out.println("打开客厅灯");
    }
    @Override
    public void off() {
        System.out.println("关闭客厅灯");
    }
}
/**
 * ⾛廊灯
 */
class HallLight implements Light{
    @Override
    public void on() {
        System.out.println("打开⾛廊灯");
    }
    @Override
    public void off() {
        System.out.println("关闭⾛廊灯");
    }
}
/**
 * 餐厅灯
 */
class DiningLight implements Light{
    @Override
    public void on() {
        System.out.println("打开餐厅灯");
    }
    @Override
    public 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: 1KB
			file-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)被输出到相应的日志文件或控制台中。

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【LDAP】LDAP 和 AD 介绍及使用 LDAP 操作 AD 域

LDAP 和 AD 介绍及使用 LDAP 操作 AD 域 1.LDAP入门1.1 定义1.2 目录结构1.3 命名格式 2.AD 入门2.1 AD 定义2.2 作用2.3 AD 域结构常用对象2.3.1 域&#xff08;Domain&#xff09;2.3.2 组织单位&#xff08;Organization Unit&#xff09;2.3.3 群组&#xff08;Group&#…

服务器数据恢复—多块磁盘离线导致阵列瘫痪,上层lun不可用的数据恢复案例

服务器存储数据恢复环境&#xff1a; 某品牌MSA2000存储&#xff0c;该存储中有一组由8块SAS硬盘&#xff08;其中有一块热备盘&#xff09;组建的RAID5阵列&#xff0c;raid5阵列上层划分了6个lun&#xff0c;均分配给HP-Unix小型机使用&#xff0c;主要数据为oracle数据库和O…

Mac 上安装多版本的 JDK 且实现 自由切换

背景 当前电脑上已经安装了 jdk8; 现在再安装 jdk17。 期望 完成 jdk17 的安装&#xff0c;并且完成 环境变量 的配置&#xff0c;实现自由切换。 前置补充知识 jdk 的安装路径 可以通过查看以下目录中的内容&#xff0c;确认当前已经安装的 jdk 版本。 cd /Library/Java/Java…

解决WordPress无法强制转换https问题

原因&#xff1a;我在用cs的时候&#xff0c;突然老鸟校园网突然断了&#xff0c;客户端cs连不上了&#xff0c;进程也杀不死&#xff0c;cpu占用100%&#xff0c;只能重启&#xff0c;但是重启后我的blog网站打不开了 开始以为是Nginx的问题&#xff0c;重启它说配置出了问题…

基于Springboot的在线博客网站

基于SpringbootVue的在线博客网站的设计与实现 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringbootMybatis工具&#xff1a;IDEA、Maven、Navicat 系统展示 用户登录 首页 博客标签 博客分类 博客列表 图库相册 后台登录 后台首页 用户管理 博客标…

Word文件导出为PDF

Word文件导出为PDF 方法一、使用Word自带另存为PDF功能 打开需要转换为PDF格式的Word文件&#xff0c;依次点击【文件】➡【另存为】➡选择文件保存类型为.PDF 使用这种方法导出的PDF可能存在Word中书签丢失的情况&#xff0c;在导出界面点击&#xff0c;选项进入详细设置 勾…

算法系列--BFS解决拓扑排序

&#x1f495;"请努力活下去"&#x1f495; 作者&#xff1a;Lvzi 文章主要内容&#xff1a;算法系列–算法系列–BFS解决拓扑排序 大家好,今天为大家带来的是算法系列--BFS解决拓扑排序 前言:什么是拓扑排序 拓扑排序–解决有顺序的排序问题(要做事情的先后顺序) …

Vulntarget-a 打靶练习

关于环境配置&#xff0c;这里就不在附上图片和说明了&#xff0c;网上一大堆&#xff0c;这里只针对自己练习&#xff0c;做一个记录。 外网信息收集 利用arpscan工具&#xff0c;扫描了当前局域网中都存在哪些主机&#xff1a; 正常来说我们不应该使用arpscan&#xff0c;而是…

各个硬件的工作原理

目录 前言 主存储器的基本组成 运算器的基本组成 控制器的基本组成 计算机的工作过程 前言 上个小节我们学习了现代计算机的基本构成都是基于冯诺依曼的思想来设计的,那么本章节要来看看主机内部三个组件的细节以及它们之间相互协调工作的. 主存储器的基本组成 这张图非常…

WPF基础应用

WPF参考原文 MVVM介绍 1.常用布局控件 1.1 布局控件 WPF&#xff08;Windows Presentation Foundation&#xff09;提供了多种布局容器来帮助开发者设计用户界面&#xff0c;以下是一些常用的布局&#xff1a; Grid: Grid是最常用的布局容器之一&#xff0c;它允许你通过定…

暗区突围端游海外版|暗区突围怎么玩 新手游玩攻略分享

游戏中健康系统与其它射击游戏有很大区别&#xff0c;根据受伤部位、伤势的不同&#xff0c;会有不同的表现。除了头部之外&#xff0c;其它部位如果损坏后继续受到伤害&#xff0c;那么伤害将会分摊到身体其它部位。在暗区内或者暗区外都可以对角色进行治疗&#xff0c;角色不…

Mybatis进阶(映射关系一对一 )

文章目录 1.基本介绍1.基本说明2.映射方式 2.配置xml方式&#xff08;多表联查&#xff09;1.数据库表设计2.新建子模块1.创建子模块2.创建基本结构 3.MyBatisUtils.java和jdbc.properties和mybatis-config.xml与原来的一致4.IdenCard.java5.Person.java6.IdenCardMapper.java7…

使用 uni-app 开发 iOS 应用的操作步骤

哈喽呀&#xff0c;大家好呀&#xff0c;淼淼又来和大家见面啦&#xff0c;上一期和大家一起探讨了使用uniapp开发iOS应用的优势及劣势之后有许多小伙伴想要尝试使用uniapp开发iOS应用&#xff0c;但是却不懂如何使用uniapp开发iOS应用&#xff0c;所以这一期淼淼就来给你们分享…

TCP三次握手,四次挥手

TCP三次握手 TCP协议 &#xff1a; 1。源端口 &#xff1a;当前的进程端口&#xff0c;2字节 2。目的端口&#xff1a;对方的端口 &#xff0c;2字节 3。序号&#xff1a;客户端或者服务器端生成的随机数 4.确认序号&#xff1a;确认上一次发送给数据对方有没有收到 5.标志…

三数之和细节

这道题看着简单&#xff0c;但是有细节要注意&#xff0c;不能有重复的三元组&#xff0c;我们也不能一开始的时候把重复的元素去除&#xff0c;如果全都是0的话&#xff0c;那么就删除的只剩下一个0了&#xff0c;显然答案是[0,0,0] class Solution { public:vector<vecto…

Jetpack Compose简介

文章目录 Jetpack Compose简介概述声明式UI和命令式UIJetpack Compose和Android View对比Compose API设计原则一切皆为函数组合优于继承单一数据源 Jetpack Compose和Android View关系使用ComposesetContent()源码ComposablePreview Jetpack Compose简介 概述 Jetpack Compos…

用龙梦迷你电脑福珑2.0做web服务器

用龙梦迷你电脑福珑2.0上做web服务器是可行的。已将一个网站源码放到该电脑&#xff0c;在局域网里可以访问网站网页。另外通过在同一局域网内的一台windows10电脑上安装花生壳软件&#xff0c;也可以在外网访问该内网服务器网站网页。该电脑的操作系统属于LAMP。在该电脑上安装…

【python】python标准化考试系统[单项选择题 简易版](源码)【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

docker挂载数据卷-以nginx为例

目录 一、什么是数据卷 二、数据卷的作用 三、如何挂载数据卷 1、创建nginx容器挂载数据卷 2、查看数据卷 3、查看数据卷详情 4、尝试在宿主机修改数据卷 5、查看容器内对应的数据卷目录 6、 访问nginx查看效果 ​​​​​​​一、什么是数据卷 挂载数据卷本质上就是实…

基于springboot实现公司日常考勤系统项目【项目源码+论文说明】

基于springboot实现公司日常考勤系统演示 摘要 目前社会当中主要特征就是对于信息的传播比较快和信息内容的安全问题&#xff0c;原本进行办公的类型都耗费了很多的资源、传播的速度也是相对较慢、准确性不高等许多的不足。这个系统就是运用计算机软件来完成对于企业当中出勤率…