Java日志系统:从基础到高级配置
立即解锁
发布时间: 2025-08-18 02:21:38 阅读量: 7 订阅数: 15 

### Java 日志系统:从基础到高级配置
在 Java 编程中,日志记录是一项至关重要的功能,它能帮助开发者监控程序运行状态、排查问题。本文将深入探讨 Java 日志系统的核心概念,包括日志命名空间、日志配置以及日志级别和过滤器的使用。
#### 1. 避免使用全局日志记录器
对于刚接触日志 API 的开发者,建议避免使用全局日志记录器。全局日志记录器通过 `Logger.getLogger("global")` 初始化,本质上是一个任意命名的日志记录器,其父日志记录器为根日志记录器。在日常开发中,使用 `Logger.getLogger("unnamed")` 能达到相同效果,更符合日志记录器的实际使用方式,还能避免在未重新配置的情况下使用全局日志记录器记录跟踪和配置信息的问题。
以下是一段配置日志记录器的代码示例:
```java
Logger logger = Logger.global.getParent();
logger.setLevel(Level.ALL);
Handler[] handlers = logger.getHandlers();
for (int i=0; i<handlers.length; i++)
handlers[i].setLevel(Level.ALL);
return Logger.global;
```
#### 2. 日志记录器命名空间
日志记录器命名空间是一个树状数据结构,用于实现 `LogManager` 类。在 API 文档和相关资料中,它有多种不同的名称,如“分层点分隔命名空间”“日志记录器命名空间”等,但都指的是同一概念。
日志记录器分为命名和匿名两种类型,通过不同的工厂方法创建:
```java
public static Logger getLogger(String name)
public static Logger getLogger(String name, String resourceBundleName)
public static Logger getAnonymousLogger()
public static Logger getAnonymousLogger(String resourceBundleName)
```
匿名日志记录器主要用于小程序,具有以下特点:
- 每次调用 `getAnonymousLogger` 方法都会返回一个新的日志记录器,且 `Logger` 类不会在命名空间中存储对其的引用。
- 无需权限即可配置,使得不可信的小程序代码也能调用配置方法。
- 有一个父日志记录器,即根日志记录器,其日志记录可能会由全局处理程序发布,除非调用 `setUseParentHandlers(false)`。
命名日志记录器存储在日志记录器命名空间中,该命名空间有三个重要用途:
1. **日志记录器共享**:通过 `getLogger("package name")` 方法,不同类可以共享同一日志记录器。通常使用包名作为日志记录器的名称,以确保一致性。
2. **日志记录发布**:默认情况下,日志记录不仅会由目标日志记录器的处理程序发布,还会由其父日志记录器的处理程序发布,直到根日志记录器。可以使用 `setUseParentHandlers` 方法控制此行为。
3. **继承父日志记录器的级别和资源包名称**:子日志记录器会继承父日志记录器的级别和资源包名称。如果未设置级别或资源包名称,则会从父日志记录器继承。
#### 3. 日志配置
日志管理器使用日志配置文件完成三个主要任务:
1. **加载属性**:将属性加载到私有 `Properties` 对象中,应用程序开发者可以使用 `LogManager` 的 `getProperty` 方法访问这些属性。
2. **配置根日志记录器和全局处理程序**:使用加载的属性或默认值配置根日志记录器和全局处理程序。
3. **配置其他日志记录器**:在创建日志记录器时,检查 `Properties` 对象中是否存在 `logger name + ".limit"` 键,如果存在则将日志记录器设置为该级别。
以下是默认日志配置文件的示例:
```properties
handlers= java.util.logging.ConsoleHandler
# To also add the FileHandler, use the following line instead.
#handlers= java.util.logging.FileHandler, java.util.logging.ConsoleHandler
.level= INFO
java.util.logging.FileHandler.pattern = %h/java%g.log
java.util.logging.FileHandler.limit = 50000
java.util.logging.FileHandler.count = 1
java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter
java.util.logging.ConsoleHandler.level = INFO
java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
```
日志配置文件的加载方式有四种:
1. **从数据库或网络加载**:通过 `java.util.logging.config.class` 系统属性指定一个无参构造函数的类,该类将成为日志配置类。
2. **从本地文件系统加载**:使用 `java.util.logging.config.file` 系统属性指定日志配置文件的路径。
3. **从 JAR 文件加载**:使用 `LogManager.getLogManager().readConfiguration(loader.getResourceAsStream("logging.properties"))` 方法加载配置文件。
4. **加载默认日志配置文件**:默认配置文件名为 `logging.properties`,位置取决于使用的是 JRE 还是 SDK。
#### 4. 日志配置实用类
为了更方便地根据日志控制属性配置处理程序,开发者可以使用以下实用类:
```java
import java.util.logging.*;
public class Loggers {
private Loggers() { } //utility class
static LogManager manager = LogManager.getLogManager();
static ClassLoader loader = ClassLoader.getSystemClassLoader();
public static void configureStreamHandler(Logger logger){
String key = logger.getName() + ".StreamHandler";
StreamHandler handler = new StreamHandler();
checkForOptionalProperties(key, handler);
logger.addHandler(handler);
}
public static void configureFileHandler(Logger logger) {
String key = logger.getName() + ".FileHandler";
String pattern = getProperty(key + ".pattern");
int limit = getIntegerProperty(key + ".limit");
int count = getIntegerProperty(key + ".count");
if (limit < 0) {
throw new LoggingPropertiesException(key + ".limit",
Integer.toString(limit));
}
if (count < 1) {
throw new LoggingPropertiesException(key + ".count",
Integer.toString(count));
}
boolean append = getBooleanProperty(key + ".append");
FileHandler handler;
try {
handler = new FileHandler(pattern,limit,count,append);
} catch (Exception e) {
throw new LoggingPropertiesException(key +
".pattern", pattern, e);
}
checkForOptionalProperties(key, handler);
logger.addHandler(handler);
}
public static void configureSocketHandler(Logger logger) {
String key = logger.getName() + ".SocketHandler";
String host = getProperty(key + ".host");
int port = getIntegerProperty(key + ".port");
SocketHandler handler;
try {
handler = new SocketHandler(host, port);
} catch (Exception e) {
throw new LoggingPropertiesExcep
```
0
0
复制全文


