java 怎么打印log
- 后端开发
- 2025-08-23
- 6
Java开发中,日志记录是调试程序、监控运行状态和排查问题的关键环节,以下是几种主流的日志打印方式及其详细实现方法:
基础方案:标准输出流
最简单直接的方式是通过System.out
或System.err
进行控制台输出。
System.out.println("普通信息"); // 标准输出(通常为绿色文本) System.err.println("错误警告"); // 错误流(红色高亮显示)
这种方式无需额外依赖库,适合临时调试,但缺乏分级管理和持久化能力,例如在循环中批量打印数据时可用格式化字符串增强可读性:
for (int i = 0; i < 5; i++) { System.out.printf("第%d次迭代 值=%.2f%n", i, Math.random()); }
JDK自带框架:java.util.logging
自JDK 1.4起内置的日志体系提供了基础架构,核心步骤包括获取Logger实例、设置级别和输出格式,典型用法如下:
import java.util.logging.; public class JULExample { private static final Logger logger = Logger.getLogger(JULExample.class.getName()); public static void main(String[] args) { logger.severe("严重错误发生!"); // SEVERE级别 logger.warning("潜在风险需要注意"); // WARNING级别 logger.info("系统启动成功"); // INFO级别 logger.config("配置参数已加载"); // CONFIG级别 logger.fine("细节调试信息"); // FINE级别(默认不启用) logger.finest("极细粒度追踪"); // FINEST级别(需显式开启) } }
若要修改默认行为,可通过Handler配置处理器,如将日志写入文件并按大小滚动分割:
FileHandler fileHandler = new FileHandler("app.log", true); // 追加模式 fileHandler.setLevel(Level.ALL); // 接收所有级别日志 logger.addHandler(fileHandler); SimpleFormatter formatter = new SimpleFormatter(); // 简单文本格式 fileHandler.setFormatter(formatter);
更复杂的场景可使用XML配置文件定义过滤器、格式化模板等高级特性。
第三方库首选:Log4j系列
作为事实上的行业标杆,Log4j家族(尤其是Log4j 2)具有高度可配置性和卓越性能,基本用法分为三步:引入依赖→获取Logger→记录不同等级的消息,以Maven项目为例,先添加依赖项:
<!-Log4j 2核心组件 --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.x</version> </dependency>
代码实现如下:
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; public class Log4jDemo { private static final Logger log = LogManager.getLogger(); public static void main(String[] args) { log.error("功能异常", new Exception("数据库连接失败")); // 带堆栈跟踪的错误日志 log.warn("资源即将耗尽"); // 预警提示 log.info("用户登录ID={}", "admin"); // 占位符自动填充参数 log.debug("解析JSON耗时{}毫秒", systemTime()); // 延迟加载的调试信息 log.trace("进入方法entry()"); // 最底层执行轨迹 } }
其强大之处在于通过log4j2.xml
配置文件实现灵活管控,例如下列配置可实现按日期归档、控制台+文件双输出、自定义图案布局:
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="WARN"> <Appenders> <Console name="Console" target="SYSTEM_OUT"> <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} %msg%n"/> </Console> <RollingFile name="File" fileName="logs/app.log" filePattern="logs/archive/app-%d{MM-dd-yyyy}.gz"> <PatternLayout> <pattern>%d{ISO8601} [%t] %p %c{1} %m%n</pattern> </PatternLayout> <Policies> <TimeBasedTriggeringPolicy interval="1" modulate="true"/> <SizeBasedTriggeringPolicy size="10MB"/> </Policies> </RollingFile> </Appenders> <Loggers> <Root level="info"> <AppenderRef ref="Console"/> <AppenderRef ref="File"/> </Root> </Loggers> </Configuration>
该配置会每天生成新的压缩日志文件,单个文件超过10MB时自动分割,同时保留最近30天的日志副本。
其他优秀替代方案对比表
特性 | java.util.logging | Log4j 2 | SLF4J+Logback |
---|---|---|---|
性能开销 | 中等 | 极低 | 非常低 |
配置灵活性 | 有限(代码/XML) | 高度自由(XML) | 依赖实现框架 |
门面模式支持 | |||
异步写入能力 | |||
MDC上下文传递 | |||
社区活跃度 | 较低 | 很高 | 极高 |
最佳实践建议
- 合理分级:ERROR仅用于系统级故障,INFO记录重要业务节点,DEBUG用于开发环境排错;
- 参数化消息:避免字符串拼接改用占位符,提升性能且支持国际化;
- 异常堆栈保留:捕获Throwable后作为第二个参数传入logging方法;
- 敏感信息过滤:生产环境关闭DEBUG级别,或使用MDC标记请求ID代替用户凭证打印;
- 资源释放:确保所有FileHandler/SocketHandler在使用完毕后正确关闭。
FAQs
Q1: 如何让日志同时输出到控制台和文件?
A: 在Log4j的配置中添加多个Appender即可实现多目标输出,例如上述XML示例中的<Console>
和<RollingFile>
组合,或者在代码中手动添加不同的Handler对象,注意不同Handler可以设置独立的过滤条件和格式样式。
Q2: 为什么有时候看不到预期的日志内容?
A: 常见原因包括:①日志级别设置过高(如仅开启INFO却试图打印DEBUG);②配置文件未被正确加载(检查路径拼写错误);③第三方库版本冲突导致静默失败,建议通过logger.isDebugEnabled()
等方法预判是否应该产生该条日志,并在启动参数中显式指定日志级别(如-DlogLevel=TRACE
)。