日誌在企業開發中有着不可或缺的做用,它能夠用以記錄用戶操做、系統運行狀態和錯誤信息。日誌記錄的好壞直接關係到系統出現問題時定位的速度。
最開始的日誌通常使用log4j,後來sun公司心有不甘,在jdk 1.4中加入了一個叫java.util.logging的日誌包,簡稱jul。兩種日誌的api確定是不一樣的,此時日誌就出現了混亂。log4j的做者Ceki Gülcü就寫了一個叫Jakarta Commons Logging的接口,簡稱jcl,來共同管理log4j和jul,而且jcl中提供了一個日誌實現simplelog。接着又改良了下log4j,寫出了logback。再後來Ceki Gülcü以爲jcl很差用(的確用問題),而後寫了一個新的接口slf4j,來共同管理這些日誌系統。接着呢Ceki Gülcü又以爲logj4性能不夠了,又寫了一個log4j2,。真是專一日誌100年啊。html
因此他們之間的關係是這樣的:java
其中slf4j並不提供日誌實現,而是使用外觀模式建立了一個接口,來統一這些日誌的api。web
這也是爲何阿里規範上強制使用slf4j的緣由:apache
【強制】應用中不可直接使用日誌系統(Log4j、Logback)中的 API,而應依賴使用日誌框架SLF4J 中的 API,使用門面模式的日誌框架,有利於維護和各個類的日誌處理方式統一。api
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final Logger logger = LoggerFactory.getLogger(Test.class);app
認識了以後接下來就是使用了,首先在maven中導入依賴:框架
<!-- log4j依賴,好像不更新了,我看版本仍是12年的 --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <!-- slf4j的依賴 --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.28</version> </dependency> <!-- 告訴slf4j使用log4j,也就是綁定 --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.28</version> <scope>test</scope> </dependency>
若是使用log4j2的話這麼配:maven
<!-- log4j2的核心 --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.12.1</version> </dependency> <!-- log4j2的api --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> <version>2.12.1</version> </dependency> <!-- slf4j綁定log4j2 --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-slf4j-impl</artifactId> <version>2.12.1</version> </dependency> <!-- slf4j的依賴 --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.28</version> </dependency>
這裏我將使用log4j2的xml和properties兩種方式來簡單配置。佈局
在resources目錄下建立log4j2.xml
:性能
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="WARN"> <!-- 輸出源的配置:日誌輸出的目的地 --> <Appenders> <!-- Console標籤;指定這是一個控制檯輸出源。 name:名稱,須要在被引用纔會生效 target: 控制檯字體的顏色 SYSTEM_ERR:紅色字體 SYSTEM_OUT:黑色字體 PatternLayout:佈局,輸出到控制檯日誌的格式。 --> <Console name="myConsole" target="SYSTEM_ERR"> <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %5level %logger{36} - %msg%n"/> </Console> <!-- 文件輸出源 fileName:指定保存日誌的文件的名字和位置。 通常寫絕對路徑。 --> <File name="myFile" fileName="D://demo.log"> <PatternLayout> <Pattern>%d %p %c{1.} [%t] %m%n</Pattern> </PatternLayout> </File> <!-- 多文件輸出源: fileName:實時記錄日誌的文件名和位置 filePattern : 文件封存的位置和格式 --> <RollingFile name="rollingFile" fileName="D://demo2.log" filePattern="D://logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz"> <PatternLayout> <Pattern>%d %p %c{1.} [%t] %m%n</Pattern> </PatternLayout> <!-- 多文件拆分的規則 --> <Policies> <!-- 基於時間的 此處interval屬性值的單位是由filePattern屬性中文件名時間精確的單位 決定的。 --> <TimeBasedTriggeringPolicy interval="1" /> <!-- 基於文件大小的 --> <SizeBasedTriggeringPolicy size="512 MB"/> </Policies> </RollingFile> </Appenders> <Loggers> <!-- 配置日誌輸出的級別的 將當前級別以及比當前級別高的消息進行輸出。 --> <Root level="trace"> <AppenderRef ref="myConsole"/> <!-- 能夠同時多種方式輸出日誌 --> <AppenderRef ref="MyFile"/> <AppenderRef ref="RollingFile"/> </Root> </Loggers> </Configuration>
log4j使用properties方式:
# 配置輸出源的 log4j.appender.輸出源名=輸出源的實現類 # 屬性的配置 log4j.appender.輸出源名.屬性名=屬性值 log4j.appender.a=org.apache.log4j.ConsoleAppender log4j.appender.a.Target=System.out log4j.appender.a.layout=org.apache.log4j.PatternLayout log4j.appender.a.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss,SSS} [%t] [%c]-[%p] %m%n log4j.appender.file=org.apache.log4j.FileAppender log4j.appender.file.File=D:/mylog.log log4j.appender.file.layout=org.apache.log4j.PatternLayout log4j.appender.file.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss,SSS} [%t] [%c]-[%p] %m%n ### log4j.rootLogger=輸出級別,輸出源1,輸出源2.... log4j.rootLogger=debug,a,file
log4j2的properties(參考):
status = warn name = MyApp appender.console.type = Console appender.console.name = consoleLogDemo appender.console.filter.threshold.type = ThresholdFilter appender.console.filter.threshold.level = debug appender.console.layout.type = PatternLayout appender.console.layout.pattern = %m%n appender.console.target = System_out appender.rolling.type = File appender.rolling.name = fileLogDemo appender.rolling.filter.threshold.type = ThresholdFilter appender.rolling.filter.threshold.level = error appender.rolling.layout.type = PatternLayout appender.rolling.layout.pattern = %d-%m%n appender.rolling.append = true appender.rolling.fileName = e:\\propertiesTest.log rootLogger.level = debug rootLogger.appenderRef.consolelogdemo.ref = consoleLogDemo rootLogger.appenderRef.filelogdemo.ref = fileLogDemo
輸出格式參數爲:
%p:輸出日誌信息的優先級,即DEBUG,INFO,WARN,ERROR,FATAL %d:輸出日誌時間點的日期或時間,默認格式爲ISO8601,能夠指定格式如:%d{yyyy/MM/dd HH:mm:ss,SSS} %r:輸出自應用程序啓動到輸出該log信息耗費的毫秒數 %t:輸出產生該日誌事件的線程名 %l:輸出日誌事件的發生位置,至關於%c.%M(%F:%L)的組合,包括類全名、方法、文件名以及在代碼中的行數 %c:輸出日誌信息所屬的類目,一般就是類全名 %M:輸出產生日誌信息的方法名 %F:輸出日誌消息產生時所在的文件名 %L:輸出代碼中的行號 %m:輸出代碼中指定的具體日誌信息 %n:輸出一個回車換行符,Windows平臺爲"rn",Unix平臺爲"n" %x:輸出和當前線程相關聯的NDC(嵌套診斷環境) %%:輸出一個"%"字符
這是幾種經常使用的配置,若是以爲不夠的話能夠查看官方文檔
順便這裏推薦個講的很詳細的博客
在log4j2中能夠這麼用:
public class MyApp { private static final Logger logger = LoggerFactory.getLogger(MyApp.class); public static void main(String[] args) { logger.warn("Hello, {}","slf4j"); } }
使用{}
做爲佔位符,性能要比log4j直接字符串拼接性能好(畢竟字符串拼接的底層原理是建立StringBuilder)
至於一大堆jar包的關係以下:
關於log4j2的以下: