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 标准库

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

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

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

适合场景

  • 小型工具/脚本
  • 对日志要求不高的场景
  • 需要避免第三方依赖的项目
相关推荐
石榴树下5 分钟前
00. 马里奥的 OAuth 2 和 OIDC 历险记
后端
是乐谷5 分钟前
阿里云杭州 AI 产品法务岗位信息分享(2025 年 8 月)
java·人工智能·阿里云·面试·职场和发展·机器人·云计算
uhakadotcom5 分钟前
开源:subdomainpy快速高效的 Python 子域名检测工具
前端·后端·面试
似水流年流不尽思念22 分钟前
容器化技术了解吗?主要解决什么问题?原理是什么?
后端
Java水解23 分钟前
Java中的四种引用类型详解:强引用、软引用、弱引用和虚引用
java·后端
i听风逝夜24 分钟前
看好了,第二遍,SpringBoot单体应用真正的零停机无缝更新代码
后端
lifallen31 分钟前
JCTools 无锁并发队列基础:ConcurrentCircularArrayQueue
java·开发语言·数据结构·算法
一叶飘零_sweeeet39 分钟前
IDEA 插件 Trae AI 全攻略
java·人工智能·intellij-idea
欧哈东哥1 小时前
【C++】标准库中用于组合多个值的数据结构pair、tuple、array...
java·数据结构·c++
python_1361 小时前
web请求和响应
java·spring·github