
本文解析Java java.util.logging 中日志级别未正确显示的根本原因——自定义 SimpleFormatter 未输出 LogRecord.getLevel(),并提供完整、可复用的格式化器改造方案,确保INFO/FINE/SEVERE等真实级别清晰可见。
本文解析java `java.util.logging` 中日志级别未正确显示的根本原因——自定义 `simpleformatter` 未输出 `logrecord.getlevel()`,并提供完整、可复用的格式化器改造方案,确保info/fine/severe等真实级别清晰可见。
问题本质并非日志级别被错误设置,而是日志输出格式缺失关键元数据。在原始代码中,GameLogger 继承自 java.util.logging.Logger,所有 log(Level, String) 调用均正确传递了对应级别(如 Level.INFO、Level.FINE),但自定义的 SimpleFormatter 仅格式化 record.getMessage(),完全忽略 record.getLevel() —— 导致终端输出中无任何级别标识,视觉上看似“全部是WARN”,实则只是级别信息彻底缺失。
更深层的设计问题在于:在 log(LogRecord) 中强行修改 record.setMessage() 属于侵入式操作,不仅破坏日志记录的原始语义(如 getLoggerName()、getSourceMethodName() 等上下文可能被干扰),还使格式化逻辑与消息构造耦合,违背单一职责原则。
✅ 正确解法是将前缀、级别、消息三者统一交由 Formatter 处理,保持 Logger 行为纯净。以下是优化后的核心实现:
Handler handler = new ConsoleHandler();
handler.setLevel(Level.ALL);
handler.setFormatter(new SimpleFormatter() {
private static final String format = "%1$s %2$-7s %3$s%n"; // 前缀 + 左对齐7字符级别 + 消息
private final String prefix; // 从外部注入,避免依赖实例字段
public CustomGameFormatter(String prefix) {
this.prefix = prefix;
}
@Override
public String format(LogRecord record) {
return String.format(format,
prefix,
record.getLevel().getName(), // 关键:显式输出真实日志级别
record.getMessage()
);
}
});
addHandler(handler);
setLevel(Level.ALL);
? 注意事项:
- 移除
log(LogRecord)的重写:不再手动拼接前缀,避免污染LogRecord原始状态;- 删除冗余的
warning()/severe()/info()重写:Logger基类已提供标准log(Level, String)封装,直接调用即可;- 级别对齐优化:
%2$-7s中的-7确保INFO(4字)、WARNING(7字)、FINEST(6字)等左对齐并预留空格,使后续消息纵向对齐,大幅提升可读性;- 线程安全:
SimpleFormatter实例应为每个 Handler 独立创建,避免共享状态引发并发问题。
最终输出效果如下(清晰区分各日志级别):
[TheBridge-GameLogger-8] INFO . Hey! This is 7/20 game tick. [TheBridge-GameLogger-8] FINE .. Hey! This is 7/20 game tick. [TheBridge-GameLogger-8] SEVERE ... Hey! This is 7/20 game tick. [TheBridge-GameLogger-8] WARNING .... Hey! This is 7/20 game tick. [TheBridge-GameLogger-8] FINEST ..... Hey! This is 7/20 game tick. [TheBridge-GameLogger-8] FINER ...... Hey! This is 7/20 game tick.
总结:Java 日志调试的核心在于分离关注点——Logger 负责日志事件的触发与过滤,Handler 负责分发,Formatter 负责呈现。任何试图在 Logger 层篡改 LogRecord 的做法,都易引发不可见的副作用。坚持“让 Formatter 做它该做的事”,才能获得稳定、可维护、可审计的日志输出。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











