Java日志框架

目录

优质文章

一、日志体系

二、日志门面 Facade

三、日志实现 Impl

四、最佳组合


优质文章

带你掌握Java各种日志框架 - 蚂蚁小哥 - 博客园

一文带你彻底掌握Log4j2 - 蚂蚁小哥 - 博客园

一、日志体系

Java日志框架_第1张图片

1)总览

sl4j是目前常用的日志门面,logback是目前常用的日志框架。

  • 门面(Facade):统一的日志 API 接口,应用程序只调用这个接口,不依赖具体实现。

  • 实现(Implementation):具体的日志框架实现,实现打印。Java日志框架_第2张图片

 企业级推荐组合

【1】SLF4J + Logback

适用: Spring Boot 默认组合 ,适合大多数企业应用,配置简单且性能稳定

【2】SLF4J + Log4j2

适用: 高性能需求场景,如金融、大数据等领域

2)桥接与绑定

桥接 Bridge 

转换已有的日志 API 到另一个门面/实现,门面 → 门面  API → 门面 。可以出现多个桥接,但是避免形成循环,比如A桥接B,同时B桥接A。使用桥接组件时 必须移除原始 API 的实现类。

依赖名称 桥接来源 → 目标 用途说明

jcl-over-slf4j

Commons Logging → SLF4J

把 JCL 的日志调用转发到 SLF4J

log4j-over-slf4j

Log4j 1.x → SLF4J

把 Log4j 1 的 API 调用转发到 SLF4J

jul-to-slf4j

JUL → SLF4J

把 JDK Logging 转发到 SLF4J

绑定Binding 

日志门面在运行时“绑定”到某一个具体的日志实现库门面 → 实现所有日志调用最终都交给它处理。一个门面只能绑定到一个实现。一般都实现“绑定 + 实现”的全部逻辑(除了Log4j 2)

依赖名称 是否内置实现 说明
logback-classic ✅ 是 标准做法
slf4j-simple ✅ 是 自带一个非常简单的实现(SimpleLogger),日志打印到控制台,适合学习和测试
slf4j-jdk14 ✅ 是 内部使用 JDK 的 java.util.logging
slf4j-nop ✅ 是 提供空实现,日志调用直接静默丢弃
slf4j-log4j12 ✅ 是  Log4j 1 自带绑定和实现
log4j-slf4j-impl ❌ 否 只是桥接器,需额外加 Log4j 2 的核心依赖

二、日志门面 Facade

1)实现机制

特性/维度 JCL  SLF4J
全称 Jakarta Commons Logging Simple Logging Facade for Java
默认行为 默认绑定到 JUL (Java Util Logging) 默认使用 NOPLogger(空实现)
依赖机制 动态绑定,运行时通过 反射机制 查找 静态绑定,运行时依赖 类路径中的实现 jar 包
接口设计 接口 宽泛笨重,不支持参数化,易出现性能问题 支持 {} 占位符参数化日志,避免字符串拼接,提高性能
上下文支持 不支持 MDC(Mapped Diagnostic Context) 支持 MDC,方便在多线程/微服务环境中传递 上下文信息
框架兼容性 容易出现 类加载冲突(特别是与某些应用服务器) 设计更清晰,避免类冲突,兼容性更好
生态现状 逐渐被淘汰,维护较弱 现代 Java 项目标准,Spring Boot 等主流框架默认集成

2)支持方式

实现类型 JCL SLF4J 
JUL 默认绑定,无需额外依赖 slf4j-jdk14
Log4j 添加 log4j依赖,直接调用 slf4j-log4j12
Logback 不支持,需 桥接到 SLF4J logback-classicSpring Boot 默认实现
简单输出 内置 SimpleLog slf4j-simple
禁用日志 无内建支持 slf4j-nop

3)代码示例

依赖引入



    commons-logging
    commons-logging
    1.2


    log4j
    log4j
    1.2.17




    org.slf4j
    slf4j-api
    1.7.36


    ch.qos.logback
    logback-classic
    1.2.11

具体使用

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.slf4j.LoggerFactory;
import java.util.logging.*;

public class LogDemo {
    private static final Logger log=Logger.getLogger("LogDemo");
    private static final Log log1 = LogFactory.getLog(LogDemo.class);
    private static final org.slf4j.Logger log2= LoggerFactory.getLogger(LogDemo.class);

    public static void main(String[] args) {
        log.info("【原生 jul】 "+ log.getClass().getName());
        log1.info("【门面 jcl】 "+ log1.getClass().getName());
        log2.info("【门面 slf4j】 "+ log2.getClass().getName());
    }
}

结果

Java日志框架_第3张图片

补充:log4j 需要在src/main/resources/log4j.properties/log4j2.properties中配置属性

三、日志实现 Impl

特性 / 框架 JUL Log4j 1.x Logback Log4j 2.x
所属组织 Oracle(JDK 内置) Apache 基金会 QOS.ch(由 Log4j 原作者开发) Apache 基金会
是否内置 ✅ JDK 自带 ❌ 需引入依赖 ❌ 需引入依赖 ❌ 需引入依赖
首次发布年代 2002 年(JDK 1.4) 2001 年 2006 年 2012 年(对 Log4j 1.x 的重构)
设计是否现代化 ❌ 老旧设计 ❌ 已弃用 ✅ 现代化架构 ✅ 现代 + 高性能架构
推荐搭配门面 可搭配 SLF4J(需桥接) 可搭配 JCL / SLF4J ✅ 默认 SLF4J 门面 ✅ 推荐配合 SLF4J
日志级别(默认) SEVERE, WARNING, INFO 等 FATAL, ERROR, WARN 等 TRACE ~ ERROR(支持 TRACE) TRACE ~ FATAL(全级别)
性能 ⚠ 中等,异步支持差 ❌ 性能差,IO阻塞 ✅ 性能较好 ✅✅ 非常优秀,异步 + 低GC
配置文件支持 .properties .properties / .xml .xml / .groovy / .json .xml / .json / .yaml / .properties
动态配置加载 ❌ 不支持 ⚠ 部分支持 ✅ 支持热加载 ✅✅ 热加载 + 自动扫描
输出格式定制性 ⚠ 一般 ✅ 支持自定义 ✅✅ 非常灵活(支持颜色等) ✅✅ 强大模板 + JSON 格式
异步日志支持 ❌ 无 ❌ 无 ✅ 内置 AsyncAppender ✅✅ 原生异步架构(Disruptor)
SLF4J 兼容性 ✅ 可桥接 ✅ 可桥接 ✅ 默认实现 ✅ 可绑定至 SLF4J
是否仍在维护 ✅ JDK 继续支持 已停止维护 ✅ QOS.ch 仍在维护 ✅ 官方持续维护
Spring Boot 支持 ⚠ 可配置启用(非默认) ❌ 弃用 ✅ 默认日志实现(Starter 依赖) ⚠ 需排除 Logback 并配置手动引入

1)实现一:JUL

package com.epi.web.log;

import com.epi.one.basic.log.WinHandler;

import java.io.IOException;
import java.util.logging.*;

public class JulLogger {

    private static final Logger log = Logger.getLogger("JulLogger");

    public static void main(String[] args) throws IOException {
        for (int i = 0; i < 4; i++) {
            julLog(i);
        }
    }

    private static void julLog(Integer handleCase) throws IOException {
        Handler handler = switch (handleCase) {
            case 0 -> new ConsoleHandler();
            case 1 -> new FileHandler("src/main/resources/txt/log.txt", false);
            case 2 -> new SocketHandler("localhost", 8088);  //开端口监听
            case 3 -> new WinHandler(); // 输出到GUI JTextArea
            default -> throw new IllegalArgumentException("Unsupported case: " + handleCase);
        };

        handler.setLevel(Level.ALL);

        log.setUseParentHandlers(false); // 关闭默认的控制台 Handler
        log.addHandler(handler);         // 使用自定义的控制台 Handler
        log.setLevel(Level.ALL);

        log.severe("SEVERE: This is an error message");
        log.warning("WARNING: This is a warning message");
        log.info("INFO: This is an info message");
        log.config("CONFIG: This is a config message");
        log.fine("FINE: This is a fine message");
        log.finer("FINER: This is a finer message");
        log.finest("FINEST: This is a finest message");
    }
}

2)实现二:Log4j 1.x


    log4j
    log4j
    1.2.17
package com.epi.web.log;

import org.apache.log4j.Logger;

public class Log4jLogger {

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

    public static void main(String[] args) {
        System.out.println(log.getClass());
        log.fatal("FATAL: 极其严重的错误");
        log.error("ERROR: 错误信息");
        log.warn("WARN: 警告信息");
        log.info("INFO: 一般信息");
        log.debug("DEBUG: 调试信息");
        log.trace("TRACE: 跟踪信息");
    }

}

3)实现三:Logback

无法脱离Slf4j使用


    org.slf4j
    slf4j-api
    2.0.16 


    ch.qos.logback
    logback-classic
    1.5.16 

package com.epi.web.log;

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

public class LogbackLogger {

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

    public static void main(String[] args) {
        log.error("ERROR: 错误");
        log.warn("WARN: 警告");
        log.info("INFO: 信息");
        log.debug("DEBUG: 调试");
        log.trace("TRACE: 跟踪");
    }
}

4)实现四:Log4j 2.x



    org.apache.logging.log4j
    log4j-api
    2.17.1



    org.apache.logging.log4j
    log4j-core
    2.17.1
package com.epi.web.log;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class Log4j2Logger {

    private static final Logger log = LogManager.getLogger(Log4j2Logger.class);

    public static void main(String[] args) {
        System.out.println(log.getClass());
        log.fatal("FATAL: 极其严重的错误");
        log.error("ERROR: 错误信息");
        log.warn("WARN: 警告信息");
        log.info("INFO: 一般信息");
        log.debug("DEBUG: 调试信息");
        log.trace("TRACE: 跟踪信息");
    }

}

四、最佳组合

1)版本适配

SLF4J  Impl 关键依赖 配置文件 备注说明
1.7.x

Logback 

1.2.x

logback-classic, logback-core logback.xml

经典稳定组合

广泛用于 Spring Boot 2.x 项目

2.0.x

Logback 

1.4.x / 1.5.x

logback-classic

logback-core(内嵌)

同上/可无

新版组合,面向 SLF4J 2.x

推荐Spring boot新项目使用

2.0.x

Log4j

2.x

log4j-slf4j2-impl

log4j-api

log4j-core

log4j2.xml

新版组合,面向 SLF4J 2.x

推荐需要高性能的项目使用

2)配置文件

文件名

框架 默认配置文件位置 支持格式
Logback classpath:logback.xml .xml, .groovy, .properties(不推荐)
Log4j 2 classpath:log4j2.xml .xml, .json, .yaml, .properties

常见XML标签

功能点 Logback Log4j 2
顶级标签
Appender
Logger
Root Logger
Layout 格式 xxx
异步日志  
……

3)MDC接入 

// java设置
MDC.put("key", "value");
// xml使用
%X{key}
package com.epi.web.log;

import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;

@Slf4j
public class MDCDemo {
    public static void mdcTest() {
        MDC.put("requestId", "REQ123456");
        log.info(log.getClass()+"  处理请求开始");  // dev logback + prd log4j2
        // 业务代码
        MDC.clear(); // 清理,避免内存泄漏
    }
}

你可能感兴趣的:(Java框架,java,logback)