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

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

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

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

适合场景

  • 小型工具/脚本
  • 对日志要求不高的场景
  • 需要避免第三方依赖的项目
相关推荐
极客先躯3 分钟前
高级java每日一道面试题-2025年4月13日-微服务篇[Nacos篇]-Nacos如何处理网络分区情况下的服务可用性问题?
java·服务器·网络·微服务·nacos·高级面试
pwzs11 分钟前
Spring MVC 执行流程全解析:从请求到响应的七步走
java·后端·spring·spring mvc
小兵张健20 分钟前
互联网必备职场知识(4)—— 共情沟通能力
后端·产品经理·运营
我该如何取个名字1 小时前
Mac配置Java的环境变量
java·开发语言·macos
kkkkatoq1 小时前
Java中的锁
java·开发语言
AskHarries1 小时前
使用 acme.sh 自动更新 SSL 证书的指南
后端
界面开发小八哥1 小时前
「Java EE开发指南」用MyEclipse开发EJB 3无状态会话Bean(二)
java·ide·java-ee·eclipse·myeclipse
LCY1331 小时前
spring security +kotlin 实现oauth2.0 认证
java·spring·kotlin
soulermax1 小时前
数字ic后端设计从入门到精通2(含fusion compiler, tcl教学)
java·linux·服务器
我的代码永没有bug2 小时前
day1-小白学习JAVA---JDK安装和环境变量配置(mac版)
java·学习·macos