JAVA日志框架之JUL、JDK原生日志框架詳解
前言
Java日志體系混亂?Java日志框架系列,清晰簡潔整理好整個Java的日志框架體系。第一篇,JDK原生日志框架——JUL。
1.概述
日志框架的核心問題:
日志是用來記錄應用的一些運行信息的。假設沒有日志框架,我們要在應用里手動實現(xiàn)日志相關功能,我們需要關注些什么?其實仔細想想無非兩點:
記錄哪些信息?
記錄到哪里去?
當然作為日志框架來說,為了方便使用,它還要關注一點就是:
如何進行方便的配置
java日志體系中是先有的log4j,后面才有了JDK自帶的jul,兩者是兩套體系,互不兼容。但其實本質上jul就是抄的log4j,其架構上都是一模一樣的。以上三點核心問題,我們看作為日志框架的開山鼻祖的log4j是怎樣解決的:

log4j給出的答案是:
記錄哪些信息——日志級別(level)
記錄到哪里去——提供不同的輸出方式(appender),文件、控制臺、其它等等
如何進行方便的配置——除硬編碼外,提供配置文件
jul是一模一樣的,其只是把appender改成了handler而已。
2.日志級別
package com.eryi;
import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Test {
@org.junit.Test
public void test1() {
//級別由低到高,默認輸出info以上級別
Logger logger = Logger.getLogger("abc");
logger.log(Level.FINEST,"FINEST level");
logger.log(Level.FINER,"FINER level");
logger.log(Level.FINE,"FINE level");
logger.log(Level.CONFIG,"CONFIG level");
logger.log(Level.INFO,"INFO level");
logger.log(Level.WARNING,"WARNING level");
logger.log(Level.SEVERE,"SEVERE level");
logger.log(Level.FINEST,"FINEST level");
System.out.println("hello");
}
}
日志為什么是紅色的?因為底層調用了system.erro,所以會輸出的字體是紅色的。
3.配置
可以用代碼的方式對JUL進行配置:
public static void main(String[] args) {
// 獲取根記錄器
Logger rootLogger = Logger.getLogger("");
// 移除默認處理器
rootLogger.setUseParentHandlers(false);
// 創(chuàng)建控制臺處理器
ConsoleHandler consoleHandler = new ConsoleHandler();
// 設置級別
consoleHandler.setLevel(Level.INFO);
// 設置自定義格式器
consoleHandler.setFormatter(new SimpleFormatter());
// 設置自定義過濾器
consoleHandler.setFilter(new CustomFilter());
// 將處理器添加到根記錄器
rootLogger.addHandler(consoleHandler);
// 輸出日志
Logger logger = Logger.getLogger(JULConfigExample.class.getName());
logger.severe("Severe message");
logger.warning("Warning message");
logger.info("Info message");
logger.config("Config message");
logger.fine("Fine message");
logger.finer("Finer message");
logger.finest("Finest message");
}
// 自定義格式器
static class SimpleFormatter extends Formatter {
@Override
public String format(LogRecord record) {
return "[" + record.getLevel() + "] - " + record.getMessage() + "\n";
}
}
// 自定義過濾器
static class CustomFilter implements Filter {
@Override
public boolean isLoggable(LogRecord record) {
// 在這里可以添加自定義的過濾邏輯
return record.getLevel().intValue() >= Level.INFO.intValue();
}
}當然更合理、更方便的方式肯定是配置文件。配置文件的示例模板在jre/lib目錄下:

把它拷貝過來改一下:

#默認配置 handlers= java.util.logging.ConsoleHandler .level= FINEST #file hander配置 java.util.logging.FileHandler.pattern = %h/java%u.log java.util.logging.FileHandler.limit = 50000 java.util.logging.FileHandler.count = 1 java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter #console handler配置 java.util.logging.ConsoleHandler.level = FINEST java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter # 具體包路徑下的日志級別 com.eryi.level = FINEST
解讀一下配置:
默認配置:
handlers: 指定默認的處理器,這里是java.util.logging.ConsoleHandler,表示使用控制臺輸出。.level: 設置默認的日志級別,這里是FINEST,表示記錄最詳細的日志。
File Handler配置:
java.util.logging.FileHandler.pattern: 設置文件處理器的日志文件的命名模式,%h表示用戶主目錄,%u表示一個唯一的數(shù)值,%g表示循環(huán)計數(shù)器。這里是%h/java%u.log。java.util.logging.FileHandler.limit: 設置文件處理器的每個日志文件的大小限制,這里是 50000 字節(jié)。java.util.logging.FileHandler.count: 設置文件處理器循環(huán)的文件數(shù),這里是 1 個。java.util.logging.FileHandler.formatter: 設置文件處理器的日志格式,這里是java.util.logging.XMLFormatter,表示使用 XML 格式。
Console Handler配置:
java.util.logging.ConsoleHandler.level: 設置控制臺處理器的日志級別,這里是FINEST。java.util.logging.ConsoleHandler.formatter: 設置控制臺處理器的日志格式,這里是java.util.logging.SimpleFormatter,表示使用簡單格式。
具體包路徑下的日志級別:
com.eryi.level: 設置特定包路徑下的日志級別,這里是FINEST,表示com.eryi包下的日志級別為最詳細。
這里要說一下為什么有了.level的配置之后還推出了專門指定某個包路徑下日志級別的配置。是因為logger之間是有父子關系的。.level會對根logger生效,其余l(xiāng)ogger是繼承自根logger的,但肯定工程上不一定是全局日志級別都是一致的,會有需求需要單獨定制某一個或者某一些的logger的日志級別。
使用效果如下:

4.繼承關系
logger之間存在父子關系。
root logger是最頂層的父logger:
Logger a = Logger.getLogger("a");
Logger b = Logger.getLogger("b");
System.out.println(a.getParent());
System.out.println(b.getParent());通過父名·子名定義父子關系:
Logger a = Logger.getLogger("a");
Logger b = Logger.getLogger("a.b");
System.out.println(a.getParent());
System.out.println(b.getParent()==a);為什么在設計的時候會存在父子關系?
Java Util Logging(JUL)的Logger之間存在父子關系,這是為了實現(xiàn)日志記錄的層次結構和更方便的配置管理。這種父子關系的設計使得日志記錄器可以繼承和繼承配置。
總結
到此這篇關于JAVA日志框架之JUL、JDK原生日志框架的文章就介紹到這了,更多相關JUL JDK原生日志框架內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
IDEA中SpringBoot項目的yml多環(huán)境配置方式
這篇文章主要介紹了IDEA中SpringBoot項目的yml多環(huán)境配置,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧2023-10-10
SpringBoot+URule實現(xiàn)可視化規(guī)則引擎的方法示例
規(guī)則引擎其實是一種組件,它可以嵌入到程序當中,將程序復雜的判斷規(guī)則從業(yè)務代碼中剝離出來,使得程序只需要關心自己的業(yè)務,而不需要去進行復雜的邏輯判斷,本文給大家介紹了SpringBoot+URule實現(xiàn)可視化規(guī)則引擎的方法示例,需要的朋友可以參考下2024-12-12
SpringBoot后端進行數(shù)據校驗JSR303的使用詳解
這篇文章主要介紹了SpringBoot后端進行數(shù)據校驗JSR303的使用詳解,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-03-03
Spring Cloud Gateway實現(xiàn)灰度發(fā)布方案
灰度發(fā)布是在微服務中的表現(xiàn)為同一服務同時上線不同版本,讓一部分用戶使用新版本來驗證新特性,如果驗證沒有問題,則將所有用戶都遷移到新版本上,本文就來介紹一下如何實現(xiàn),感興趣的可以了解一下2023-12-12
深入學習Java單元測試(Junit+Mock+代碼覆蓋率)
在做單元測試時,代碼覆蓋率常常被拿來作為衡量測試好壞的指標,甚至,用代碼覆蓋率來考核測試任務完成情況,比如,代碼覆蓋率必須達到80%或 90%。下面我們就來詳細學習下java單元測試吧2019-06-06

