⭐⭐⭐ Spring Boot 项目实战 ⭐⭐⭐ Spring Cloud 项目实战
《Dubbo 实现原理与源码解析 —— 精品合集》 《Netty 实现原理与源码解析 —— 精品合集》
《Spring 实现原理与源码解析 —— 精品合集》 《MyBatis 实现原理与源码解析 —— 精品合集》
《Spring MVC 实现原理与源码解析 —— 精品合集》 《数据库实体设计合集》
《Spring Boot 实现原理与源码解析 —— 精品合集》 《Java 面试题 + Java 学习指南》

摘要: 原创出处 夏壹分享 「夏壹」欢迎转载,保留摘要,谢谢!


🙂🙂🙂关注微信公众号:【芋道源码】有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言都将得到认真回复。甚至不知道如何读源码也可以请教噢。
  4. 新的源码解析文章实时收到通知。每周更新一篇左右。
  5. 认真的源码交流微信群。

前言

我们都知道一个真相,在开发中,日志记录扮演着极其重要的角色。

无论是在开发调试阶段,还是在生产环境中,日志都能够帮助我们追踪系统状态、定位问题、分析性能。

甚至在出现问题时,日志往往是最有力的线索,基本都用它排查问题以及快速定位问题。

然而,我们在敲代码时,如果随便使用 System.out.println() 来输出日志,就会导致以下一系列问题,这是完全没必要的损耗,例如:

  • 性能差:System.out.println() 直接输出到控制台,性能较差。
  • 不易管理: 日志信息没有级别区分,也没有统一的格式。
  • 不方便追踪: 没有详细的日志记录,尤其在生产环境,错误时很难追溯问题的根源。

因此,使用专业的日志框架进行日志记录显得尤为重要。

今天,我们将通过一个具体的实战案例,学习如何使用 SLF4J + Logback 配合 Lombok 提供的 @Slf4j 注解,封装出一个统一的日志工具类,帮助我们高效、优雅地管理日志输出。

为什么使用日志工具而非 System.out?

理由很简单,使用 System.out.println() 进行日志输出虽然简单,但它存在许多弊端。 尤其是随着项目的复杂度提高,逐渐暴露出性能、管理和可维护性等问题:

  • 性能问题:System.out.println() 直接输出到控制台,每次调用都会消耗一定的系统资源。

    在高并发、频繁调用的情况下,控制台输出会显得非常低效,严重影响系统性能。

  • 日志级别管理: 日志记录的级别(如调试信息、错误信息、警告信息等)在 System.out.println() 中完全无法区分。

    而使用日志框架时,我们可以清晰地定义日志级别,例如 DEBUG、 INFO、 WARN、 ERROR 等。不同级别的日志可以分别输出到控制台或文件中,帮助我们更好地管理日志信息。

  • 格式统一性: 在项目中,每个模块、每个开发人员可能都会采用不同的日志格式,导致日志混乱、难以阅读。

    使用日志工具类可以帮助我们统一日志输出格式,方便调试和查看。

因此,选择使用专门的日志框架来替代 System.out.println(),不仅能提高性能和可维护性,还能帮助我们更好地追踪问题。

封装统一日志输出格式与级别

使用 SLF4J 和 Logback 组合

SLF4J(Simple Logging Facade for Java),它是 Java 中最常用的日志接口。 它并不直接提供日志实现,而是通过 API 抽象化了日志框架。

Logback 是与 SLF4J 配合使用的日志框架,它提供了强大的日志功能,能够管理日志的输出级别、格式化、存储等,谁用谁爽,不信你试试。

配置 Logback,引入相关依赖

首先,我们需要引入 SLF4J 和 Logback 相关的依赖。

在 Maven 中,我们可以像这样引入:

<dependencies>
<!-- SLF4J 核心接口依赖 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.32</version>
</dependency>

<!-- Logback 日志实现核心包 -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.6</version>
</dependency>

<!-- Logback 核心依赖 -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.6</version>
</dependency>
</dependencies>

接下来,我们还需要在 src/main/resources 目录下创建 logback.xml 配置文件,配置日志输出格式、输出级别等:

<configuration>
<!-- 定义控制台输出器 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<!-- 日志格式:时间 - 级别 [线程名] 类名 - 日志内容 -->
<pattern>%d{yyyy-MM-dd HH:mm:ss} - %5p [%t] %logger{36} - %msg%n</pattern>
</encoder>
</appender>

<!-- 根日志配置,级别为debug -->
<root level="debug">
<!-- 关联控制台输出器 -->
<appender-ref ref="STDOUT" />
</root>
</configuration>

在上面这个配置中,我们可以设置日志输出的格式,包括输出时间、日志级别、线程名、类名、日志内容等。

日志级别被设置为 DEBUG,意味着所有 DEBUG 级别及以上的日志信息都会被输出。

当然这个级别在生产环境可以设置为更高一级的,比如 ERROR,这样直接可对标排查报错等异常。

使用 Lombok 的 @Slf4j 注解

在传统日志框架中,开发者需要手动创建 Logger 对象,但使用 Lombok 提供的 @Slf4j 注解后,我们无需再手动声明 Logger。

Lombok 会自动为我们生成 Logger 实例。

import lombok.extern.slf4j.Slf4j;

// 添加@Slf4j注解,自动生成log对象
@Slf4j
publicclass LogExample {

public static void main(String[] args) {
// 输出INFO级别的日志
log.info("This is an info message");
// 输出DEBUG级别的日志
log.debug("This is a debug message");
// 输出ERROR级别的日志
log.error("This is an error message");
// 输出WARN级别的日志
log.warn("This is a warning message");
}
}

通过使用 @Slf4j 注解,我们不需要显式地创建 Logger 对象,直接使用 log 进行日志记录,简化了代码。

实战:API 日志统一、异常追踪日志输出

API 日志统一

在实际项目中,尤其是 Web 项目中,我们往往需要统一记录 API 请求和响应的日志。 通过日志工具,我们能够记录请求的详细信息,包括请求的 URL、参数、请求方法等,还能记录响应内容和状态。

以下是一个简单的示例,展示如何记录 API 日志:

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

// 开启日志功能
@Slf4j
@RestController
publicclass APIController {

// 定义一个测试接口
@GetMapping("/api/test")
public String testAPI() {
// 记录请求到达日志
log.info("API request received for /api/test");

String response = "Hello, world!";

// 记录响应内容日志
log.info("API response: {}", response);

return response;
}
}

在上面这个demo中, log.info() 记录了 API 请求的日志和响应的日志。

你可以轻松地根据业务需求修改日志级别,例如在调试时使用 DEBUG,在出错时使用 ERROR 等。

异常追踪日志输出

在系统出现异常时,日志记录尤为重要,它能帮助开发者快速定位问题。

在生产环境中,异常日志通常包含详细的堆栈信息,这有助于我们追踪问题的根本原因。

以下是如何记录异常日志的示例:

import lombok.extern.slf4j.Slf4j;

@Slf4j
publicclass ExceptionHandler {

public void handleException() {
try {
// 模拟出现异常的代码
int result = 10 / 0;
} catch (Exception e) {
// 记录异常信息,第二个参数传入异常对象会自动打印堆栈
log.error("An error occurred: ", e);
}
}
}

在代码中,我们就通过 log.error() 来记录发生异常时的堆栈信息。

这样,当问题发生时,我们可以迅速查看到详细的异常信息,帮助我们定位问题。

文章目录
  1. 1. 前言
  2. 2. 为什么使用日志工具而非 System.out?
  3. 3. 封装统一日志输出格式与级别
    1. 3.1. 使用 SLF4J 和 Logback 组合
    2. 3.2. 配置 Logback,引入相关依赖
    3. 3.3. 使用 Lombok 的 @Slf4j 注解
  4. 4. 实战:API 日志统一、异常追踪日志输出
    1. 4.1. API 日志统一
    2. 4.2. 异常追踪日志输出