0Pricing
Java Academy · 课时

SLF4J 外观与日志记录器

在正确的级别记录日志

SLF4J 外观与日志记录器 是 CoddyKit 上的免费 Java Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Java Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Java Academy 课程共包含 4 节课。

什么是 SLF4J?

SLF4J(Java 的简单日志门面)是一种抽象层。您可以针对它的 API 编写代码,而由 Logback 或 Log4j2 这样的后端实际执行日志记录。

这样,库就可以记录日志,而不会强迫应用程序使用某个特定实现。

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Main {
    private static final Logger log = LoggerFactory.getLogger(Main.class);
    public static void main(String[] args) {
        log.info("Application started");
    }
}

获取日志记录器

使用 LoggerFactory.getLogger(MyClass.class) 为每个类创建一个日志记录器。

按照惯例,这个字段声明为 private static final,名称为 log 或 logger。该类会成为日志记录器的名称,并显示在输出中。

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class OrderService {
    private static final Logger log = LoggerFactory.getLogger(OrderService.class);
    void placeOrder(String id) {
        log.info("Placing order {}", id);
    }
}

五个级别

SLF4J 日志记录器为每个级别提供一个方法:

  • log.trace(...)
  • log.debug(...)
  • log.info(...)
  • log.warn(...)
  • log.error(...)
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Main {
    private static final Logger log = LoggerFactory.getLogger(Main.class);
    public static void main(String[] args) {
        log.trace("entering main");
        log.debug("args length = {}", args.length);
        log.info("service is up");
        log.warn("cache miss");
        log.error("failed to connect");
    }
}

选择正确的级别

指导原则:

  • ERROR:需要人工处理的真实故障。
  • WARN:可以恢复的异常情况。
  • INFO:重要的生命周期事件。
  • DEBUG:供开发人员使用的诊断信息,在生产环境中关闭。
  • TRACE:极其详细的跟踪信息。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class PaymentService {
    private static final Logger log = LoggerFactory.getLogger(PaymentService.class);
    void charge(int cents) {
        if (cents <= 0) { log.warn("non-positive charge: {}", cents); return; }
        log.info("charged {} cents", cents);
    }
}

日志记录器名称与层级

日志记录器名称按照以点分隔的软件包构成层级结构。名为 com.example.svc 的日志记录器是 com.example 的子级。

除非被覆盖,否则对父级所做的配置会应用于子级,因此您可以按软件包设置级别。

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Main {
    public static void main(String[] args) {
        Logger a = LoggerFactory.getLogger("com.example.app");
        Logger b = LoggerFactory.getLogger("com.example.app.db");
        a.info("parent logger");
        b.debug("child inherits parent's level unless overridden");
    }
}

保护开销较大的调用

对于开销较大的消息构造,请使用 isDebugEnabled() 进行保护,这样只有在该级别处于启用状态时才会执行相关工作。

使用参数化日志记录(下一课会介绍)时,您很少需要这样做;但如果要自行构造字符串,这一点就非常重要。

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Main {
    private static final Logger log = LoggerFactory.getLogger(Main.class);
    static String heavyDump() { return "...large state..."; }
    public static void main(String[] args) {
        if (log.isDebugEnabled()) {
            log.debug("state: {}", heavyDump());
        }
    }
}

记录异常

若要记录带有完整堆栈跟踪的异常,请将 Throwable 作为最后一个参数传入。

不要将异常放入占位符中;请将它放在消息之后传入。

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Main {
    private static final Logger log = LoggerFactory.getLogger(Main.class);
    public static void main(String[] args) {
        try {
            throw new IllegalStateException("boom");
        } catch (Exception e) {
            log.error("Operation failed for id {}", 42, e);
        }
    }
}

每个类使用一个日志记录器

将日志记录器声明为静态最终字段,并且只声明一次。不要在方法内部创建日志记录器,因为这会浪费工作量,也会失去使用类名作为日志记录器名称的优势。

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class UserRepository {
    // Good: one shared logger named after the class
    private static final Logger log = LoggerFactory.getLogger(UserRepository.class);
    void save(String user) { log.debug("saving {}", user); }
}

SLF4J 与后端

SLF4J 只是 API。在运行时,它会绑定到类路径上的任意后端。

  • 添加 logback-classic:SLF4J 使用 Logback。
  • 添加 log4j-slf4j2-impl:SLF4J 使用 Log4j2。

您的代码完全不需要修改。

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Main {
    private static final Logger log = LoggerFactory.getLogger(Main.class);
    public static void main(String[] args) {
        // Same code, different backend depending on classpath
        log.info("backend-agnostic logging");
    }
}

避免记录敏感数据

绝不要记录密码、令牌或完整的信用卡号码。日志通常会被发送到多个系统,并且长期保留。

记录日志前,请遮盖或省略敏感字段。

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Main {
    private static final Logger log = LoggerFactory.getLogger(Main.class);
    static String mask(String card) { return "****" + card.substring(card.length() - 4); }
    public static void main(String[] args) {
        log.info("charged card {}", mask("4111111111111234"));
    }
}

一个贴近实际的服务

综合运用:让一个小型服务在适当的级别记录日志,并处理异常路径。

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class EmailService {
    private static final Logger log = LoggerFactory.getLogger(EmailService.class);
    void send(String to) {
        log.debug("preparing email to {}", to);
        try {
            if (to == null) throw new IllegalArgumentException("null recipient");
            log.info("email sent to {}", to);
        } catch (Exception e) {
            log.error("failed to send email", e);
        }
    }
}

快速检查

测试您对 SLF4J 基础知识的掌握程度。

回顾

您已经学习了 SLF4J 门面:

  • 每个类获取一个 private static final Logger。
  • 恰当地使用五个级别方法。
  • 日志记录器名称具有层级结构,可以按软件包进行控制。
  • 将 Throwable 放在最后传入,以记录堆栈跟踪;绝不要记录机密信息。

接下来将学习高效的参数化消息。

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Main {
    private static final Logger log = LoggerFactory.getLogger(Main.class);
    public static void main(String[] args) {
        log.info("SLF4J facade recap complete");
    }
}

常见问题解答

「SLF4J 外观与日志记录器」课时是免费的吗?

是的 — 「SLF4J 外观与日志记录器」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Java Academy 课程的其余内容,请升级到 CoddyKit PRO。 Java Academy 课程共包含 4 节课。

「SLF4J 外观与日志记录器」这节课中我会学到什么?

在正确的级别记录日志 你通过在浏览器中直接运行的动手代码来练习 Java Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Java Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Java Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。

「SLF4J 外观与日志记录器」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Java Academy 课中编写并运行代码吗?

能。每节 Java Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 结构化日志为何重要
  2. SLF4J 外观与日志记录器
  3. 参数化日志记录
  4. 配置 Logback
← 返回 Java Academy