Java提供了很多第三方的日志框架可供使用,按照現在的設計理念,一般把日志框架分成門面(Facade)
部分和具體實現(Implementation)
部分,門面(Facade)
提供了抽象的api規范,實現(Implementation)
負責實現api完成具體的日志記錄功能。開發者在使用日志框架時使用的是門面提供的api,可以根據實際情況靈活的選擇不同的api實現。
一、java.util.logging
1、概述
java.util.logging
是Java標準庫自帶的日志框架,使用時無需引入第三方依賴,提供的功能相對簡單,一般不在實際項目中使用。
package com.demo;
import java.util.logging.Logger;class LoggingDemoApplicationTests {Logger logger = Logger.getLogger(LoggingDemoApplicationTests.class.getName());public static void main(String[] args) {logger.info("test logging.");}}
2、配置
java.util.logging
的配置文件是.proerties
文件,默認路徑是$JAVA_HOME/lib/logging.proerties
,可以通過JVM參數或代碼指定自定義的配置文件。
使用JVM參數-Djava.util.logging.config.file
指定:
java -Djava.util.logging.config.file=path/logging.properties mainApp.jar
使用代碼指定:
package org.example;
public class JavaLoggingTest {public static void main(String[] args) {try (InputStream inputStream = Main.class.getResourceAsStream("config/logging.properties")) {LogManager.getLogManager().readConfiguration(inputStream);} catch (Exception e) {e.printStackTrace();}// 日志記錄示例java.util.logging.Logger logger = java.util.logging.Logger.getLogger(Main.class.getName());logger.info("This is an info message.");}
}
配置文件內容:
# 全局日志級別
.level= INFO# 控制臺處理器的日志級別
java.util.logging.ConsoleHandler.level = INFO
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter# 文件處理器的日志級別
java.util.logging.FileHandler.level = INFO
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.SimpleFormatter# 自定義日志記錄器的日志級別
com.example.JavaLoggingTest.level = FINE
二、commons-logging
1、概述
commons-logging
(JCL)提供了一輕量和獨立于其他日志框架的個Log
接口,它給開發者提供了簡單的日志抽象,允許開發者像使用插件一樣選擇具體的日志實現。
也就是說commons-logging
是一個日志門面,其不提供具體的日志實現。commons-logging
提供包裝了其他日志API和后端的Log
接口的實現,包括Log4j2.x
、Slf4j
、java.lang.logging
,除此之外還有一些老的日志框架Log4j1.x
、Avalon LogKit
等的實現,只不過默認是禁用的。
2、配置
commons-logging
主要有兩個抽象類:org.apache.commons.logging.Log
和org.apache.commons.logging.LogFactory
,其中Log
提供了統一的日志接口,而LogFactory
作為一個工廠類提供了創建Log
的方法。開發者在使用時可以手動指定一個Log
的具體實現(例如前面提到的commons-logging
提供的其他日志API的包裝實現或者自己實現一個Log
),LogFactory
作為創建Log
的工廠接口,一般情況下我們不需要手動指定,除非需要使用其他高級功能。
JCL提供了三類LogFactory
的實現,Log4jApiLogFactory
、Slf4jLogFactory
和LogFactoryImpl
。默認情況下JCL將按照下面的方式選擇一個LogFactory
:
- 如果Java類路徑里包含
Log4j API
,并且開發者沒有手動將Log4j API的實現重定向到SLF4j
,則Log4jApiLogFactory
將會被使用,JCL的日志調用將會交給Log4j API
實現。 - 如果類路徑里存在
SLF4j
,則Slf4jLogFactory
將會被使用,JCL的日志調用將會交給SLF4j
實現。 - 如果都不存在,則JCL將會使用
LogFactoryImpl
。
對于LogFactoryImpl
來說,其通過下面的順序查找Log
的實現,直到找到第一個可用的Log
時,終止查找流程:
- 查找配置屬性
org.apache.commons.logging.Log
是否設置了值,開發者可以通過在Java代碼里設置org.apache.commons.logging.Log
的值,或者在Java類路徑下定義一個名字為commons-logging.properties
的配置文件,在配置文件里設置commons-logging.properties
的值,commons-logging.properties
文件里的配置將作為LogFactory
的屬性。如果類路徑下有多個配置文件的情況下,可以在配置文件里指定一個priority屬性指明優先級,優先級相同的兩個文件將會使用第一個找到那個。 - 查找系統配置
org.apache.commons.logging.Log
的值,如果存在這個系統屬性將會使用這個屬性指定的值作為Log的實現。 - 查找
java.logging
是否可用,如果可用將會使用Jdk14Logger
類作為Log
的實現。 - 如果前面幾個步驟都沒有找到
Log
的具體實現,將會使用默認的實現類SimpleLog
作為Log
的實現。
三、Log4j 1.x
Log4j 1.x 是Apache軟件基金會開發的一個流行的Java日志框架,廣泛應用于早期的Java項目中。它提供了強大的日志記錄功能,支持靈活的配置和多種日志輸出方式。Log4j 1.x 已經停止維護,被Log4j2.x取代。我們不不需要對其詳細的做過多的了解。
Log4j 1.x使用類路徑下命名為log4j.properties
的文件作為配置文件,開發者可以在該文件里配置相關屬性。
我們這里重點介紹對于一些依賴Log4j1.x
的老舊項目和第三方庫,我們在依賴這些項目時應該怎么處理它們的日志輸出。如果我們有一個老項目project-log4j1
使用了Log4j1.x作為其日志框架,現在我們有一個新項目需要依賴project-log4j1
,但我們的新項目使用SLF4j
作為日志框架,這時候我們應該怎么處理project-log4j
的日志輸出呢?對此,SLF4j
提供了適配器log4j-over-slf4j用來把調用Log4j1.x的日志操作重定向到SLF4j
的日志輸出,我們只需要在項目里引入對應的依賴并提供SLF4j
的實現和配置即可。
<dependency><groupId>org.slf4j</groupId><artifactId>log4j-over-slf4j</artifactId><version>2.0.17</version>
</dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>2.0.17</version>
</dependency>
當然SLF4j
作為一個日志門面并不提供日志輸出的具體實現,至于使用什么框架作為SLF4j
的具體實現對log4j-over-slf4j
無影響。
除了SLF4j
之外,apache
也提供了相應的庫log4j-1.2-api用來將對Log4j1.x的調用重定向到Log4j2.x的實現,使用只需要引入依賴即可
<dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-1.2-api</artifactId><version>2.24.3</version>
</dependency>
<dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-api</artifactId><version>2.24.3</version>
</dependency><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-core</artifactId><version>2.24.3</version>
</dependency>
如果使用Log4j2.x我們需要按照Log4j2.x的格式提供配置文件。
四、Log4j 2.x
1、概述
Log4j2.x是Apache Log4j1.x的升級版本,是一個支持異步日志記錄的高性能日志框架,它解決了 Log4j 1.x 的許多問題,并引入了許多新特性。Log4j2.x采用接口和實現分離的設計方式,從而提高了靈活性和可擴展性,其中log4j-api
提供了抽象api,log4j-core
提供了對應的實現,開發者在使用時可以只引入log4j-api
,而使用其他例如SLF4j+Logback
日志框架作為具體實現。
通過log4j-to-slf4j可以實現把對log4j-api
的調用重定向到SLF4j
,從而實現使用log4j-api
作為門面,使用SLF4j+Logback
作為日志具體實現的需求。
<dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-to-slf4j</artifactId><version>2.x.x</version>
</dependency>
<dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.36</version>
</dependency>
<dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.2.11</version>
</dependency>
此時,日志配置按照Logback的格式進行配置即可。
2、配置
Log4j2.x
提供了多種格式的配置文件,默認情況下,Log4j2.x將會按照下面的名稱順序掃描類路徑找到配置文件:
log4j2-test<contextName>.<extension>
log4j2-test.<extension>
log4j2<contextName>.<extension>
log4j2.<extension>
其中contextName
表示上下文信息,一般情況下我們使用log4j.<extension>
命名的配置文件就能滿足需求,extension
表示文件類型,例如log4j2.properties
Log4j2.x的配置文件支持xml
、json
、ymal
、Properties
格式,如果同時存在多個類型的配置文件,則將會按照下面的優先級查找:
- XML
- JSON
- YAML
- Properties
使用JSON格式的配置文件需要添加jackson-databind
依賴,使用yaml格式的配置文件需要添加jackson-dataformat-yaml
依賴
<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.18.0</version><scope>runtime</scope>
</dependency><dependency><groupId>com.fasterxml.jackson.dataformat</groupId><artifactId>jackson-dataformat-yaml</artifactId><version>2.18.0</version><scope>runtime</scope>
</dependency>
xml類型配置文件log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<Configuration xmlns="https://logging.apache.org/xml/ns"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="https://logging.apache.org/xml/nshttps://logging.apache.org/xml/ns/log4j-config-2.xsd"><Appenders><Console name="CONSOLE"><PatternLayout pattern="%p - %m%n"/></Console><File name="MAIN" fileName="logs/main.log"><JsonTemplateLayout/></File><File name="DEBUG_LOG" fileName="logs/debug.log"><PatternLayout pattern="%d [%t] %p %c - %m%n"/></File></Appenders><Loggers><Root level="INFO"><AppenderRef ref="CONSOLE" level="WARN"/><AppenderRef ref="MAIN"/></Root><Logger name="org.example" level="DEBUG"><AppenderRef ref="DEBUG_LOG"/></Logger></Loggers>
</Configuration>
json格式配置文件log4j2.json
{"Configuration": {"Appenders": {"Console": {"name": "CONSOLE","PatternLayout": {"pattern": "%p - %m%n"}},"File": [{"name": "MAIN","fileName": "logs/main.log","JsonTemplateLayout": {}},{"name": "DEBUG_LOG","fileName": "logs/debug.log","PatternLayout": {"pattern": "%d [%t] %p %c - %m%n"}}]},"Loggers": {"Root": {"level": "INFO","AppenderRef": [{"ref": "CONSOLE","level": "WARN"},{"ref": "MAIN"}]},"Logger": {"name": "org.example","level": "DEBUG","AppenderRef": {"ref": "DEBUG_LOG"}}}}
}
ymal格式配置文件log4j2.yaml
Configuration:Appenders:Console:name: "CONSOLE"PatternLayout:pattern: "%p - %m%n"File:- name: "MAIN"fileName: "logs/main.log"JsonTemplateLayout: {}- name: "DEBUG_LOG"fileName: "logs/debug.log"PatternLayout:pattern: "%d [%t] %p %c - %m%n"Loggers:Root:level: "INFO"AppenderRef:- ref: "CONSOLE"level: "WARN"- ref: "MAIN"Logger:name: "org.example"level: "DEBUG"AppenderRef:ref: "DEBUG_LOG"
Properties格式配置文件log4j2.properties
appender.0.type = Console
appender.0.name = CONSOLE
appender.0.layout.type = PatternLayout
appender.0.layout.pattern = %p - %m%nappender.1.type = File
appender.1.name = MAIN
appender.1.fileName = logs/main.log
appender.1.layout.type = JsonTemplateLayoutappender.2.type = File
appender.2.name = DEBUG_LOG
appender.2.fileName = logs/debug.log
appender.2.layout.type = PatternLayout
appender.2.layout.pattern = %d [%t] %p %c - %m%nrootLogger.level = INFO
rootLogger.appenderRef.0.ref = CONSOLE
rootLogger.appenderRef.0.level = WARN
rootLogger.appenderRef.1.ref = MAINlogger.0.name = org.example
logger.0.level = DEBUG
logger.0.appenderRef.0.ref = DEBUG_LOG
五、Slf4j
1、概述
Slf4j
是一個日志門面(Facade),只提供了日志接口抽象,使用Slf4j
需要引入具體的日志實現,一般情況下使用Logback
作為Slf4j
的實現,因為Logback
就是SLF4j
api的標準實現。
使用SLF4j+Logback作為日志框架需要引入如下依賴:
<dependency> <groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>2.0.17</version>
</dependency><!-- JAVAX EE -->
<dependency> <groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.3.14</version>
</dependency><!-- Jakarta EE -->
<dependency> <groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.5.15</version>
</dependency>
Logback提供了logback-core
模塊實現了基礎的日志功能,logback-classic
在logback-core
的基礎上實現了SLF4j
API,在配合SLF4j
使用時,一般情況下我們只需引入logback-classic
即可。
除了Logback外,開發者也可以使用其他日志框架作為SLF4j
的實現,例如Log4j2.x
。apache提供了log4j-slf4j2-impl用來把SLF4j的API調用重定向到Log4j2.x。
<dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-slf4j2-impl</artifactId><version>2.24.3</version><scope>test</scope>
</dependency><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-api</artifactId><version>2.x.x</version>
</dependency>
<dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-core</artifactId><version>2.x.x</version>
</dependency>
<dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.36</version>
</dependency>
把SLF4j
橋接到Log4j2.x
后,配置文件將使用相應的Log4j2.x
配置文件。
也可以使用slf4j-log4j12
將SLF4j
重定向到Log4j1.x,使用slf4j-jdk14
將SLF4j
重定向到java.util.logging
,不過正常情況下不這樣使用,現在項目中使用最多的就是SLF4j+Logback
的搭配方式。
2、配置
LogBack使用XML作為配置文件的格式,默認情況下Logback將會在類路徑下按順序查找命名為logback-test.xml
或logback.xml
的配置文件
logback.xml
<configuration><appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"><!-- encoders are assigned the typech.qos.logback.classic.encoder.PatternLayoutEncoder by default --><encoder><pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} -%kvp- %msg%n</pattern></encoder></appender><root level="debug"><appender-ref ref="STDOUT" /></root>
</configuration>
六、其他框架
除了上面幾個常用的日志框架以外,Java還有很多其他的日志框架,這里只介紹在實際項目中比較常見的幾種。