Java.util.logging (JUL) 终极指南:从基础配置到高级玩法

一、快速入门:JUL基础用法

1. 基础日志输出

java 复制代码
import java.util.logging.Logger;
import java.util.logging.Level;

public class BasicJUL {
    // 获取Logger实例(推荐使用类全限定名)
    private static final Logger LOG = Logger.getLogger(BasicJUL.class.getName());

    public static void main(String[] args) {
        // 输出不同级别日志
        LOG.info("程序启动");     // 信息级别
        LOG.warning("内存不足");  // 警告级别
        LOG.severe("致命错误");   // 严重错误
        
        // 带参数的日志
        String userName = "张三";
        LOG.log(Level.INFO, "用户登录: {0}", userName);
        
        // 记录异常
        try {
            throw new IOException("文件未找到");
        } catch (IOException e) {
            LOG.log(Level.SEVERE, "发生IO异常", e);
        }
    }
}

二、核心配置:logging.properties详解

1. 默认配置问题

  • 默认级别:INFO(只输出INFO及以上级别)

  • 默认输出:控制台(ConsoleHandler)

  • 默认格式:简单文本(无时间戳)

2. 自定义配置文件

ini 复制代码
# logging.properties
# 全局日志级别
.level= INFO

# 控制台处理器配置
handlers= java.util.logging.ConsoleHandler
java.util.logging.ConsoleHandler.level = ALL
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
java.util.logging.SimpleFormatter.format=[%1$tF %1$tT] [%4$-7s] %5$s %n

# 文件处理器配置
handlers= java.util.logging.FileHandler
java.util.logging.FileHandler.pattern = ./logs/app_%u.log
java.util.logging.FileHandler.limit = 10485760  # 10MB
java.util.logging.FileHandler.count = 5
java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter

3. 加载配置文件

csharp 复制代码
// 启动时指定配置文件
public static void main(String[] args) throws IOException {
    InputStream is = BasicJUL.class.getResourceAsStream("/logging.properties");
    LogManager.getLogManager().readConfiguration(is);
    // ...其他代码...
}

三、高级玩法:自定义Handler与Filter

1. 自定义邮件报警Handler

less 复制代码
public class EmailHandler extends Handler {
    @Override
    public void publish(LogRecord record) {
        if (record.getLevel().intValue() >= Level.SEVERE.intValue()) {
            // 调用邮件发送API
            sendAlertEmail(record.getMessage());
        }
    }

    @Override public void flush() {}
    @Override public void close() {}
    
    private void sendAlertEmail(String msg) {
        // 实现邮件发送逻辑
    }
}

// 注册自定义Handler
LOG.addHandler(new EmailHandler());

2. 日志 过滤器

less 复制代码
// 只记录包含特定关键字的日志
LOG.setFilter(record -> record.getMessage().contains("支付"));

// 组合过滤条件
LOG.setFilter(record -> 
    record.getLevel() == Level.SEVERE || 
    record.getMessage().startsWith("用户")
);

四、性能优化:避免常见陷阱

1. 参数化日志(避免无效字符串拼接)

less 复制代码
// 错误写法(即使日志级别关闭也会执行字符串拼接)
LOG.fine("用户信息:" + user.toString());

// 正确写法(使用lambda延迟计算)
LOG.fine(() -> "用户信息:" + user.toString());

2. 异步日志处理

scala 复制代码
// 自定义异步Handler
public class AsyncHandler extends Handler {
    private final Executor executor = Executors.newSingleThreadExecutor();

    @Override
    public void publish(LogRecord record) {
        executor.execute(() -> {
            // 转发给其他Handler处理
            getHandlers().forEach(h -> h.publish(record));
        });
    }
    // ...其他方法...
}

// 使用方式
Handler asyncHandler = new AsyncHandler();
asyncHandler.addHandler(new ConsoleHandler());
LOG.addHandler(asyncHandler);

五、与其他框架整合

1. 在Spring Boot中使用JUL

ini 复制代码
# application.properties
# 禁用Spring Boot默认的Logback
logging.config=classpath:logging.properties
logging.level.org.springframework=WARN
logging.level.com.yourpackage=DEBUG

2. 与SLF4J 桥接

xml 复制代码
<!-- pom.xml -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>jul-to-slf4j</artifactId>
    <version>2.0.7</version>
</dependency>
arduino 复制代码
// 启动类配置
public class Main {
    static {
        SLF4JBridgeHandler.removeHandlersForRootLogger();
        SLF4JBridgeHandler.install();
    }
}

六、常见问题排雷指南

问题现象 解决方案
日志文件不生成 检查文件路径权限,确认FileHandler配置正确
日志级别设置不生效 确保没有代码动态修改Logger级别
日志格式混乱 检查SimpleFormatter.format的转义字符
性能低下 使用异步Handler,避免同步阻塞
第三方库日志过多 单独设置包级别:com.third.package.level = WARNING

JUL哲学

虽然功能不如 Log4j / Logback 强大,但JUL作为Java 标准库

  • 无需额外依赖,适合简单应用

  • 可通过配置满足基本需求

  • 与其他日志框架桥接方便

适合场景

  • 小型工具/脚本
  • 对日志要求不高的场景
  • 需要避免第三方依赖的项目
相关推荐
独立开阀者_FwtCoder7 分钟前
深入解密Node共享内存:这个原生模块让你的多进程应用性能翻倍
前端·javascript·后端
Asthenia04129 分钟前
深入剖析 Spring Cloud Feign 的 Contract 组件:设计与哲学
后端
Asthenia041218 分钟前
Feign 原理:Client 的实现与选型(ApacheHttpClient/OkHttp)/Feign超时控制
后端
开心就好202519 分钟前
Flutter实战】文本组件及五大案例
后端
Ai 编码助手22 分钟前
Golang并发编程:Data Race检测与解决方案
开发语言·后端·golang
宦如云28 分钟前
Assembly语言的嵌入式调试
开发语言·后端·golang
日月星辰Ace34 分钟前
SpringBootTest 不能使用构造器注入
java·spring boot
Gvemis⁹1 小时前
Scala总结(三)
开发语言·后端·scala
一只小闪闪1 小时前
langchain4j搭建失物招领系统(五)---实现失物登记功能-大模型流式输出
java·人工智能·后端
SimonKing1 小时前
Kafka 4.0.0震撼来袭,彻底摒弃Zookeeper
java·后端·架构