simpleformatter 不支持直接自定义时间格式、类名占位符或消息模板,必须继承并重写 format(logrecord) 方法;可通过重写灵活控制时间格式、类名提取、字段顺序及消息拼接,注意使用 formatmessage()、避免 simpledateformat 线程安全问题,并在异步场景下 fallback 到 getloggername()。

SimpleFormatter 本身不支持直接自定义时间格式、类名占位符或消息模板,它只提供固定格式:日志级别 日志时间 类名 方法名 行号 消息(如 INFO: Wed Jan 01 12:00:00 CST 2025 MyClass.doWork:42 Hello)。若需灵活控制时间格式、省略/替换类名、调整字段顺序或添加自定义内容,必须**继承 SimpleFormatter 并重写 format(LogRecord) 方法**。
1. 继承 SimpleFormatter 重写 format 方法
这是最直接可控的方式。通过覆盖 format(),你可以完全决定每条日志的字符串结构:
- 调用
record.getLevel()获取日志级别 - 用
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date(record.getMillis()))格式化时间 - 用
record.getSourceClassName()或record.getLoggerName()获取类名(注意:前者依赖栈帧,可能为 null;后者是 Logger 名,更稳定) - 用
record.getMessage()和record.getParameters()拼接格式化后的消息(若使用logger.log(Level.INFO, "User {0} logged in", userId))
2. 示例:输出 [时间][类名][级别] 消息
(简洁可读风格,适合开发调试)```java
public class CustomFormatter extends SimpleFormatter {
private final DateFormat df = new SimpleDateFormat("HH:mm:ss.SSS");
@Override
public String format(LogRecord record) {
String time = df.format(new Date(record.getMillis()));
String className = record.getSourceClassName() != null
? record.getSourceClassName().substring(record.getSourceClassName().lastIndexOf('.') + 1)
: "unknown";
String level = record.getLevel().getName();
String msg = formatMessage(record); // 处理参数占位符,如 {0}
return String.format("[%s][%s][%s] %s%n", time, className, level, msg);
}
}
```
然后注册到 Handler:
ConsoleHandler handler = new ConsoleHandler();<br>handler.setFormatter(new CustomFormatter());<br>Logger.getLogger("myapp").addHandler(handler);
3. 注意事项与常见坑
-
时间精度:SimpleFormatter 默认用
getMillis(),毫秒级准确;避免用System.currentTimeMillis()替代,否则丢失原始时间戳 -
类名可靠性:在异步、代理、Lambda 场景下
getSourceClassName()常为null,建议 fallback 到record.getLoggerName() -
消息格式化:务必调用
formatMessage(record)而非直接取record.getMessage(),否则无法解析{0}等参数 -
线程安全:SimpleDateFormat 非线程安全,应每个 formatter 实例独享一个(如上面示例中作为成员变量初始化),或改用
DateTimeFormatter(Java 8+)
4. 替代方案:用 java.util.logging.Formatter 的其他实现
如果定制需求复杂(如 JSON 输出、多行堆栈、MDC 支持),SimpleFormatter 继承方式会越来越重。此时可考虑:
- 直接实现
Formatter接口(更彻底自由) - 迁移到 Log4j2 或 SLF4J + Logback(它们的 PatternLayout / PatternLayoutEncoder 原生支持
%d{HH:mm:ss.SSS} [%c] %-5p %m%n这类模板语法) - 仅对 java.util.logging 做轻量增强时,继承 SimpleFormatter 是最轻量、侵入最小的选择
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











