缘博客
发布日期

Java日志:SLF4J与Logback

作者
  • 姓名
    社交账号

为什么需要日志

开发阶段经常会使用:

System.out.println("根据ID删除部门:" + id);

这种方式虽然可以看到结果,但存在明显问题:

  • 只能简单输出到控制台
  • 无法方便地控制输出级别
  • 难以统一管理
  • 不方便将日志保存到文件
  • 项目变大后难以维护

程序中的日志用于记录应用运行过程中的信息。

常见用途:

  • 数据追踪
  • 问题排查
  • 性能优化
  • 系统监控
  • 异常定位

Java常见日志技术

JUL

JUL 即:

java.util.logging

是 Java SE 自带的日志框架,配置相对简单,但灵活性和功能相对有限。

Log4j

Log4j 是常见的日志框架之一,支持多种日志输出方式和灵活配置。

Logback

Logback 提供了完善的日志功能,并支持灵活配置。Spring Boot 默认日志体系中会使用到 Logback。

SLF4J

SLF4J 全称 Simple Logging Facade for Java,本身更像一层日志门面,为应用提供统一的日志接口。

业务代码
 SLF4J
Logback / 其他日志实现

Logback快速入门

Spring Boot 项目已经通过相关依赖间接引入日志组件,一般不需要再单独添加。

普通项目可以引入:

<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
</dependency>

创建Logger对象

private static final Logger log =
        LoggerFactory.getLogger(DeptController.class);

然后记录日志:

log.debug("开始执行...");
log.info("查询部门成功");
log.warn("参数可能存在问题");
log.error("系统执行异常");

参数化日志

相比:

log.info("根据ID删除部门:" + id);

更推荐:

log.info("根据ID删除部门:{}", id);

多个参数:

log.info(
    "修改部门,id:{},name:{}",
    dept.getId(),
    dept.getName()
);

在Controller中使用

@RestController
public class DeptController {

    private static final Logger log =
            LoggerFactory.getLogger(DeptController.class);

    @Autowired
    private DeptService deptService;

    @DeleteMapping("/depts")
    public Result delete(Integer id) {

        log.info("根据ID删除部门:{}", id);

        deptService.delete(id);

        return Result.success();
    }
}

Lombok的@Slf4j

如果项目使用 Lombok,可以通过 @Slf4j 自动生成日志对象。

@Slf4j
@RestController
public class DeptController {

    @DeleteMapping("/depts")
    public Result delete(Integer id) {

        log.info("根据ID删除部门:{}", id);

        return Result.success();
    }
}

这样不需要再手写 LoggerFactory.getLogger(...)


Logback配置文件

Logback 常用配置文件:

logback.xml

配置文件可以控制:

  • 日志输出格式
  • 日志输出位置
  • 日志级别
  • 日志文件
  • 是否开启日志

控制台输出

<appender
    name="STDOUT"
    class="ch.qos.logback.core.ConsoleAppender">

    <!-- 输出格式等配置 -->

</appender>

文件输出

<appender
    name="FILE"
    class="ch.qos.logback.core.rolling.RollingFileAppender">

    <!-- 文件路径、滚动策略等配置 -->

</appender>

然后在根节点中引用:

<root level="INFO">
    <appender-ref ref="STDOUT"/>
    <appender-ref ref="FILE"/>
</root>

这样日志既可以输出到控制台,也可以保存到系统文件。


日志级别

常见日志级别从低到高:

TRACE
DEBUG
INFO
WARN
ERROR
级别用途
TRACE非常详细的运行轨迹,使用较少
DEBUG调试信息
INFO正常运行过程中的重要信息
WARN潜在问题或警告
ERROR错误和异常

记录方式:

log.trace("...");
log.debug("...");
log.info("...");
log.warn("...");
log.error("...");

日志级别过滤

如果配置:

<root level="INFO">
    <appender-ref ref="STDOUT"/>
    <appender-ref ref="FILE"/>
</root>

那么只会输出 INFO 及以上级别:

INFO
WARN
ERROR

TRACEDEBUG 不会输出。


常见使用场景

DEBUG

log.debug("进入用户查询逻辑");

主要用于开发调试信息。

INFO

log.info("用户登录成功,userId:{}", userId);

用于记录系统正常运行中的关键事件。

WARN

log.warn("接口请求过于频繁,userId:{}", userId);

用于记录潜在问题。

ERROR

log.error("保存部门失败", e);

用于记录错误和异常。


日志替代控制台输出

正式项目中更推荐:

log.info(...)
log.debug(...)
log.warn(...)
log.error(...)

日志框架可以通过配置统一控制输出内容、输出位置、日志级别和格式,因此比 System.out.println(...) 更适合真实项目。