Java日志總結

開發中,日志記錄是不可或缺的一部分,應用日志的記錄主要用于:記錄操作軌跡數據、監控系統運行情況、系統故障定位問題,日志的重要性不言而喻,想要快速定位問題,日志分析是個重要的手段,Java也提供了多種日志框架來進行有效的日志管理。本文將探討Java常用的日志框架以及使用案例。

一、發展歷史

  • 1996: Log4j 1.x 由瑞士程序員CeKi Gülcü 發布
  • 2002: JDK 1.4 發布,包含 JUL(java.util.logging,位于java.logging模塊下),是 JDK 官方自帶的日志框架。JUL 性能很差,使用比較少。
  • 2002: Apache推出了Jakarta Commons Logging(簡稱JCL)日志接口
  • 2010: Slf4j 發布
  • 2009: Logback 發布
  • 2014: Log4j2 發布

二、日志框架

現有的一些日志框架:

  • 日志實現:JUL(java.util.logging)、logback、log4j、log4j2
  • 日志門面:JCL(Jakarta Commons Logging)、Slf4j(Simple Logging Facade for Java)

在這里插入圖片描述

1.Log4j

官方網站: http://logging.apache.org/log4j/1.2
Log4j 是 Apache 的一個開源項目,創始人 Ceki Gulcu。是 Java 領域資格最老,應用最廣的日志工具。Log4j 中有三個主要組件:

  • loggers(記錄器) - 負責接收并記錄日志信息。
  • appenders(輸出器) - 負責發布日志信息,定義了日志信息的目的地(如控制臺、文件、數據庫等)。
  • layouts(布局) -負責定義日志輸出的格式。
    這種解耦的設計使得Log4j非常靈活,可以很容易地根據項目的需求進行定制。

1.1 log4j使用:

1).添加maven依賴

<!-- log4j -->
<dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version>
</dependency>

2).resources目錄下創建log4j.properties文件(log4j支持兩種配置文件格式:一種是XML格式的文件,一種是properties屬性文件)

log4j.rootLogger=INFO,M,C,E
log4j.additivity.monitorLogger=false
# INFO級別文件輸出配置
log4j.appender.M=org.apache.log4j.DailyRollingFileAppender
log4j.appender.M.File=/logs/info.log
log4j.appender.M.ImmediateFlush=false
log4j.appender.M.BufferedIO=true
log4j.appender.M.BufferSize=16384
log4j.appender.M.Append=true
log4j.appender.M.Threshold=INFO
log4j.appender.M.DatePattern='.'yyyy-MM-dd
log4j.appender.M.layout=org.apache.log4j.PatternLayout
log4j.appender.M.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss} %p %l %m %n
# ERROR級別文件輸出配置
log4j.appender.E=org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File=/logs/error.log
log4j.appender.E.ImmediateFlush=true
log4j.appender.E.Append=true
log4j.appender.E.Threshold=ERROR
log4j.appender.E.DatePattern='.'yyyy-MM-dd
log4j.appender.E.layout=org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss} %p %l %m %n
# 控制臺輸出配置
log4j.appender.C=org.apache.log4j.ConsoleAppender
log4j.appender.C.Threshold=INFO
log4j.appender.C.layout=org.apache.log4j.PatternLayout
log4j.appender.C.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [%t] %-5p %l %m %n

appender配置常使用的類如下:

org.apache.log4j.ConsoleAppender(控制臺)
org.apache.log4j.FileAppender(文件)
org.apache.log4j.DailyRollingFileAppender(每天產生一個日志文件)
org.apache.log4j.RollingFileAppender(文件大小到達指定尺寸的時候產生一個新的文件)
org.apache.log4j.WriterAppender(將日志信息以流格式發送到任意指定的地方)

layouts常用配置類:

org.apache.log4j.HTMLLayout(以HTML表格形式布局)
org.apache.log4j.PatternLayout(可以靈活地指定布局模式)
org.apache.log4j.SimpleLayout(包含日志信息的級別和信息字符串)
org.apache.log4j.TTCCLayout(包含日志產生的時間、線程、類別等信息)

layout格式化打印參數:

* log4j 采用類似 C 語言的 printf 函數的打印格式格式化日志信息,具體的占位符及其含義如下:
%m   輸出代碼中指定的日志信息
%p   輸出優先級,及 DEBUGINFO%n   換行符(Windows平臺的換行符為 "\n"Unix 平臺為 "\n"%r   輸出自應用啟動到輸出該 log 信息耗費的毫秒數
%c   輸出打印語句所屬的類的全名
%t   輸出產生該日志的線程全名
%d   輸出服務器當前時間,默認為 ISO8601,也可以指定格式,如:%d{yyyy年MM月dd日 
HH:mm:ss}
%l   輸出日志時間發生的位置,包括類名、線程、及在代碼中的行數。如:
Test.main(Test.java:10)
%F   輸出日志消息產生時所在的文件名稱
%L   輸出代碼中的行號 
%%   輸出一個 "%" 字符* 可以在 % 與字符之間加上修飾符來控制最小寬度、最大寬度和文本的對其方式。如:
%5c     輸出category名稱,最小寬度是5,category<5,默認的情況下右對齊
%-5c    輸出category名稱,最小寬度是5,category<5"-"號指定左對齊,會有空格
%.5c    輸出category名稱,最大寬度是5,category>5,就會將左邊多出的字符截掉,<5不
會有空格
%20.30c category名稱<20補空格,并且右對齊,>30字符,就從左邊交遠銷出的字符截掉

xml文件格式如下:

<?xml version="1.0" encoding="UTF-8"?><Configuration><Appenders><Appender><Filters><LevelRangeFilter minLevel="..." maxLevel="..." onMatch="..." onMismatch="..."/></Filters><PatternLayout pattern="..." charset="..."/><Policies><CronTriggeringPolicy schedule="..."/><SizeBasedTriggeringPolicy size="..."/><TimeBasedTriggeringPolicy /></Policies></Appender><Appender>...</Appender></Appenders><Loggers><Logger><AppenderRef ref="..."></Logger><Root><AppenderRef ref="..."></Root></Loggers></Configuration>

3) log4j日志打印測試

import org.apache.log4j.Logger;
public class Log4jTest {@Testpublic void testLog4j(){// 1.創建日志記錄器對象,使用靜態方法創建Logger logger = Logger.getLogger("com.example.logtest.Log4jTest");// 記錄debug級別的信息logger.debug("This is debug message.");// 記錄info級別的信息logger.info("This is info message.");// 記錄error級別的信息logger.error("This is error message.");}
}

2.JUL

JUL全稱Java util Logging是Java原生的日志框架,使用時不需要另外引用第三方類庫,JUL主要用于小型應用程序中,其設計原理基于幾個核心組件:

  • Logger:記錄器,是應用程序訪問日志系統的入口點。應用程序通過獲取Logger對象,并調用其API來發布日志信息。Logger對象通常與特定的類或代碼塊相關聯,以便能夠精確地跟蹤和記錄日志。
  • Handler:也被稱為Appenders,每個Logger都會關聯一個或多個Handler。Handler負責處理Logger傳遞過來的日志信息,并將其發送到指定的目的地,如控制臺、文件、網絡上的其他日志服務或操作系統日志等。Handler的具體實現決定了日志記錄的位置和方式。
  • Filter:過濾器,用于根據特定條件篩選日志信息。開發者可以根據需要定制哪些信息會被記錄,哪些信息會被忽略,從而實現對日志信息的精細控制。
  • Level:日志的輸出級別。每條日志消息都有一個關聯的級別,如DEBUG、INFO、WARN、ERROR等。這些級別粗略地指導了日志消息的重要性和緊迫性。

JUL的配置相對簡單,配置文件通常使用.properties或XML格式,雖然是JDK自帶的日志庫,JUL使用的并不廣泛,原因是因為JUL早期存在性能問題,到JDK1.5上才有了不錯的進步,但現在和Logback/Log4j2相比還是有所不如

2.1 測試案例

import java.util.logging.Level;
import java.util.logging.Logger;
public class JULTest {@Testpublic void testQuick(){// 1.創建日志記錄器對象,使用靜態方法創建Logger logger = Logger.getLogger("com.example.logtest.JULTest");// 2.日志記錄輸出logger.info("hello JUL");// 通用方法輸出logger.log(Level.INFO, "info msg");// 通過占位符輸出logger.log(Level.INFO, "name: {0},age: {1}", new Object[]{"zhangsan",20});}
}

2.2 日志級別

java.util.logging.Level中定義了7個日志的級別

// 關閉日志記錄
public static final Level OFF = new Level("OFF",Integer.MAX_VALUE, defaultBundle);
// 錯誤--最高的日志級別
public static final Level SEVERE = new Level("SEVERE",1000, defaultBundle);
// 警告
public static final Level WARNING = new Level("WARNING", 900, defaultBundle);
// 消息(默認級別)
public static final Level INFO = new Level("INFO", 800, defaultBundle);
// 配置
public static final Level CONFIG = new Level("CONFIG", 700, defaultBundle);
// 詳細信息(少)
public static final Level FINE = new Level("FINE", 500, defaultBundle);
// 詳細信息(中)
public static final Level FINER = new Level("FINER", 400, defaultBundle);
// 詳細信息(多)-- 最低級的日志級別
public static final Level FINEST = new Level("FINEST", 300, defaultBundle);
// 啟用所有消息日志
public static final Level ALL = new Level("ALL", Integer.MIN_VALUE, defaultBundle);

2.3 日志配置

如果我們沒有添加配置,JUL默認的配置文件:JAVA_HOME/jre/lib/logging.properties

############################################################
#  	Default Logging Configuration File
#
# You can use a different file by specifying a filename
# with the java.util.logging.config.file system property.  
# For example java -Djava.util.logging.config.file=myfile
########################################################################################################################
#  	Global properties
############################################################# "handlers" specifies a comma separated list of log Handler 
# classes.  These handlers will be installed during VM startup.
# Note that these classes must be on the system classpath.
# By default we only configure a ConsoleHandler, which will only
# show messages at the INFO and above levels.
## RootLogger使用的處理器
handlers= java.util.logging.ConsoleHandler# To also add the FileHandler, use the following line instead.
#handlers= java.util.logging.FileHandler, java.util.logging.ConsoleHandler# Default global logging level.
# This specifies which kinds of events are logged across
# all loggers.  For any given facility this global level
# can be overriden by a facility specific level
# Note that the ConsoleHandler also has a separate level
# setting to limit messages printed to the console.
# RootLogger日志等級
.level= INFO############################################################
# Handler specific properties.
# Describes specific configuration info for Handlers.
############################################################
## 文件處理器
# default file output is in user's home directory.
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
## 控制臺處理器
# Limit the message that are printed on the console to INFO and above.
java.util.logging.ConsoleHandler.level = INFO
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter# Example to customize the SimpleFormatter output format 
# to print one-line log message like this:
#     <level>: <log message> [<date/time>]
#
# java.util.logging.SimpleFormatter.format=%4$s: %5$s [%1$tc]%n############################################################
# Facility specific properties.
# Provides extra control for each logger.
############################################################# For example, set the com.xyz.foo logger to only log SEVERE
# messages:
com.xyz.foo.level = SEVERE

自定義日志級別及配置

@Test
public void test2() throws IOException {
// 1.獲取日志記錄器對象
Logger logger = Logger.getLogger("com.example.logtest.JULTest");// 關閉系統默認配置
logger.setUseParentHandlers(false);
// 一、自定義配置日志級別// 創建ConsoleHandler 控制臺輸出
ConsoleHandler consoleHandler = new ConsoleHandler();
// 創建簡單格式轉換對象
SimpleFormatter simpleFormatter = new SimpleFormatter();
// 進行關聯
consoleHandler.setFormatter(simpleFormatter);
logger.addHandler(consoleHandler);
// 配置日志具體級別
logger.setLevel(Level.ALL);
consoleHandler.setLevel(Level.ALL);// 二、輸出到日志文件
FileHandler fileHandler = new FileHandler("d:/jul.log");
// 進行關聯
fileHandler.setFormatter(simpleFormatter);
logger.addHandler(fileHandler);// 日志記錄輸出
logger.severe("severe");
logger.warning("warning");
logger.info("info"); // 默認日志輸出級別
logger.config("config");
logger.fine("fine");
logger.finer("finer");
logger.finest("finest");
}

2.4 日志對象Logger的父子關系

JUL中Logger對象存在父子關系,也就是父親Logger的設置,同時能夠作用于兒子,這種父子關系是通過樹狀結構包路徑進行存儲,如下:logger1的日志設置,對logger2也能生效。

@Testpublic void test3() throws Exception {// 日志記錄器對象父子關系Logger logger1 = Logger.getLogger("com.fang");Logger logger2 = Logger.getLogger("com.fang.log");System.out.println(logger2.getParent() == logger1);// 所有日志記錄器對象的頂級父元素  class為java.util.logging.LogManagerSystem.out.println("logger2 parent:" + logger2.getParent() + ",name:" + logger2.getParent().getName());// 一、自定義日志級別// a.關閉系統默認配置logger1.setUseParentHandlers(false);// b.創建handler對象ConsoleHandler consoleHandler = new ConsoleHandler();// c.創建formatter對象SimpleFormatter simpleFormatter = new SimpleFormatter();// d.進行關聯consoleHandler.setFormatter(simpleFormatter);logger1.addHandler(consoleHandler);// e.設置日志級別logger1.setLevel(Level.ALL);consoleHandler.setLevel(Level.ALL);// 測試日志記錄器對象父子關系logger2.severe("severe");logger2.warning("warning");logger2.info("info");logger2.config("config");logger2.fine("fine");logger2.finer("finer");logger2.finest("finest");}

測試結果:

true
logger2 parent:java.util.logging.Logger@6ec8211c,name:com.fang
五月 10, 2024 12:09:45 上午 com.example.logtest.JULTest testLogParent
嚴重: severe
五月 10, 2024 12:09:45 上午 com.example.logtest.JULTest testLogParent
警告: warning
五月 10, 2024 12:09:45 上午 com.example.logtest.JULTest testLogParent
信息: info
五月 10, 2024 12:09:45 上午 com.example.logtest.JULTest testLogParent
配置: config
五月 10, 2024 12:09:45 上午 com.example.logtest.JULTest testLogParent
詳細: fine
五月 10, 2024 12:09:45 上午 com.example.logtest.JULTest testLogParent
較詳細: finer
五月 10, 2024 12:09:45 上午 com.example.logtest.JULTest testLogParent
非常詳細: finest

3.Slf4j

Slf4J(Simple Logging Facade for Java)是一個用于Java的簡單日志門面(Facade)主要是為了給Java日志訪問提供一套標準、規范的API框架,它本身并不提供具體的日志實現,具體的實現可以交由其他日志框架,例如 log4j 、 logback、java.util.logging等。當然 Slf4J 自己也提供了功能較為簡單的實現 slf4j-simple,但是一般很少用到。SLF4J 的作者就是 log4j 的作者 Ceki Gülcü,他宣稱 SLF4J 比 log4j 更有效率,而且比 Apache Commons Logging (JCL) 簡單、穩定。
官網:https://www.slf4j.org

3.1 Slf4j的官網架構圖

在這里插入圖片描述
上面架構圖中可以看到,第一層是應用層,第二層即為slf4j提供的抽象接口:slf4j-api.jar,第三層的話藍色的(2列5列6列)是日志的實現,而且是直接實現slf4j-api.jar相關接口,湖藍色(3列4列)是適配層,與上面的slf4j-api接口以及第4層具體日志框架(log4j、jul)的適配。從上圖也可以看到logback是直接實現了slf4j的接口的,而log4j在被slf4j調用的時候需要一個適配層。

reload4j:reload4j是Apache log4j版本1.x的一個分支,由于log4j存在一些安全漏洞,Apache社區和其他開發者開始尋求解決方案,reload4j就是其中之一。通過使用slf4j-reload4j,開發者可以在不修改太多代碼的情況下,將他們的應用程序從log4j 1.x遷移到reload4j,從而提高應用程序的安全性和穩定性。

slf4j的主要搭配如下

  • Slf4j+logback slf4j-api.jar+logback-classic.jar+logback-core.jar
  • Slf4j+log4j slf4j-api.jar+slf4j-log4j12.jar+log4j.jar
  • Slf4j+jul slf4j-api.jar+slf4j-jdk14.jar
  • Slf4j無日志實現 slf4j-api.jar+slf4j-nop.jar

官網第二張圖(橋接策略)
在這里插入圖片描述
可以看到,上面含義是如果我們已經使用了其他日志框架的api,想轉到另一種日志框架api,該如何使用橋接的jar包,如從logback到log4j,JUL到log4j等,本質是通過將一種框架日志交給slf4j,slf4j再通過橋接包到轉給另一種框架日志輸出,總的來說為以下情況:

  • 在使用JCL,則可以通過:jcl-over-slf4j.jar
  • 在使用log4j,則可以通過:log4j-over-slf4j.jar
  • 在使用JUL,則可通過jul-to-slf4j.jar
    在這里插入圖片描述
    注意: 雖然使用 log4j-over-slf4j 可以實現 Log4j 橋接到 SLF4J,也可以使用 slf4j-log4j12 實現 SLF4J 適配到 Log4j,但是它不能同時使用它們,否則就會產生死循環。jcl 和 jul 也是同樣的道理,jcl-over-slf4j.jar和slf4j-jcl.jar不能同時出現,jul-over-slf4j.jar和slf4j-log4j12.jar不能同時出現。

4.Logback

官網:https://logback.qos.ch/
Logback是由Ceki Gülcü(同時也是SLF4J的作者)創建的新一代日志框架,旨在解決Log4J的部分性能瓶頸和設計局限。Logback不僅實現了SLF4J API,還具有高度優化的性能、豐富的配置選項和強大的擴展能力。SpringBoot底層也是使用slf4j+logback的方式進行日志記錄。
Logback主要分為三個模塊:

  • logback-core :其它兩個模塊的基礎模塊
  • logback-classic :它是log4j的一個改良版本,同時它完整實現了slf4j API
  • logback-access :訪問模塊與Servlet容器集成提供通過Http來訪問日志的功能

4.1 Logback 使用示例

1)添加依賴

<dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.25</version>
</dependency>
<dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.2.3</version>
</dependency>

實際開發中我們可以直接引入spring-boot-starter-web依賴,因為spring-boot-starter-web包含了spring-boot-starter 而spring-boot-starter包含了spring-boot-starter-logging

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId>
</dependency>

2)配置文件
logback會依次讀取以下類型配置文件:

  1. logback.groovy
  2. logback-test.xml
  3. logback.xml
    如果均不存在會采用默認配置

logback-spring.yml

<?xml version="1.0" encoding="utf-8"?>
<!--配置文件說明:
共有一個父標簽、兩種屬性、三個節點:
1.一個父標簽:configuration
2. 兩種屬性:contextName和property
3. 三個節點:appender、root、logger主要就是appender追加到哪里:控制臺/文件,然后采用哪種pattern(在property定義了pattern格式)
然后就是logger和root配置,指定日志輸出級別,以及引用哪種appender
-->
<configuration><!--根節點<configuration>包含的屬性:scan:當此屬性設置為true時,配置文件如果發生改變,將會被重新加載,默認值為true。scanPeriod:設置監測配置文件是否有修改的時間間隔,如果沒有給出時間單位,默認單位是毫秒。當scan為true時,此屬性生效。默認的時間間隔為1分鐘。debug:當此屬性設置為true時,將打印出logback內部日志信息,實時查看logback運行狀態。默認值為false。--><contextName>logback-spring-demo-dev</contextName><property name="pattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg %n"/><property name="pattern-color"value="%yellow(%d{yyyy-MM-dd HH:mm:ss.SSS}) [%thread] %highlight(%-5level) %green(%logger{50}) - %highlight(%msg) %n"/><!--文件路徑輸出說明,會自動生成文件夾及log文件,但是由于我這個是多模塊,默認生成在父目錄下的logs文件夾下面,所以要在子模塊下生成要再加一個路徑--><property name="LOG_HOME" value="./springboot_log/logs"/><!-- 控制臺輸出 --><appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"><!--ThresholdFilter為系統定義的攔截器,例如我們用ThresholdFilter來過濾掉ERROR級別以下的日志不輸出到文件中。如果不用記得注釋掉,不然你控制臺會發現沒日志~--><!--<filter class="ch.qos.logback.classic.filter.ThresholdFilter">--><!--<level>ERROR</level>--><!--</filter>--><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><pattern>${pattern}</pattern></encoder></appender><!-- 控制臺輸出-帶顏色 --><appender name="CONSOLE-WITH-COLOR" class="ch.qos.logback.core.ConsoleAppender"><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><pattern>${pattern-color}</pattern></encoder></appender><!-- 文件輸出 --><appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>${LOG_HOME}/%d.%i.log</fileNamePattern><timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"><maxFileSize>10MB</maxFileSize></timeBasedFileNamingAndTriggeringPolicy><maxHistory>30</maxHistory></rollingPolicy><encoder><pattern>${pattern}</pattern></encoder></appender><!--相當于全局的配置--><root level="INFO"><appender-ref ref="CONSOLE-WITH-COLOR"/><appender-ref ref="FILE"/></root><!--1. root和logger是父子的關系。Logger的appender根據參數additivity決定是否要疊加root的appender,logger的級別是其自身定義的級別,和root的級別沒什么關系。2. logger對單個包或類添加配置,相當于局部配置,root相當于全局配置如果logger里面配置了additivity="false",就會覆蓋root的,只打印一遍;但是additivity="true",就會向上層再次傳遞,不會覆蓋,而是打印兩遍!--><!--相當于局部配置:配置特定類/包使用不同的日志輸出器appender:TestControoler2的會輸出兩遍,additivity="true"--><logger name="com.apple.controller.TestController2" level="INFO" additivity="true"><appender-ref ref="CONSOLE"/></logger></configuration>

3)測試

@Slf4j
@RestController
public class TestController {@RequestMapping("/index")public String index(){log.info("==========hello logback=============");return "hello logback";}
}

在這里插入圖片描述

5.JCL(Jakarta Commons Logging)

官網:https://commons.apache.org/proper/commons-logging/
JCL是Apache基金會所屬的項目,是一套Java日志接口,之前叫Jakarta Commons Logging,后更名為Commons Logging, 它本身并不提供日志的具體實現,(當然,commons-logging內部有一個SimpleLog但是功能非常常弱 ,所以一般不會單獨使用它),而是在運行時綁定具體的日志組件來工作(如Log4j、JUL )。

JCL兩個基本抽象類:

  • Log:日志記錄器
  • LogFactory:日志工廠(負責創建Log實例)
    在這里插入圖片描述

5.1 JCL例子

maven依賴:

<dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId><version>1.2</version> 
</dependency>

測試

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;public class JCLTest {@Testpublic void testJCL(){// 創建日志對象Log log = LogFactory.getLog(JCLTest.class);// 記錄debug級別的信息log.debug("This is debug message.");// 記錄info級別的信息log.info("This is info message.");// 記錄error級別的信息log.error("This is error message.");}
}

6.log4j2

官網:https://logging.apache.org/log4j/2.x/
Apache Log4J曾一度是Java世界中最流行的日志框架之一,以其靈活性和模塊化設計著稱。然而,隨著時間推移,原版Log4J暴露出了一些性能和功能上的短板。于是,Apache基金會推出了Log4J2,這是一個經過徹底重構并優化的新版本,引入了許多新特性,主要有:

  • 異常處理,在 logback中,Appender中的異常不會被應用感知到,但是在log4j2中,提供了一些異 常處理機制。
  • 性能提升, log4j2相較于log4j 和logback都具有很明顯的性能提升,后面會有官方測試的數據。
  • 自動重載配置,參考了 logback的設計,當然會提供自動刷新參數配置,最實用的就是我們在生產 上可以動態的修改日志的級別而不需要重啟應用。
  • 無垃圾機制, log4j2在大部分情況下,都可以使用其設計的一套無垃圾機制,避免頻繁的日志收集導致的jvm gc

6.1案例實現:

1)引入依賴:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-log4j2</artifactId><version>2.6.13</version>
</dependency>

2) log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" monitorInterval="5"><properties><property name="LOG_HOME">D:/logs</property></properties><Appenders><Console name="Console" target="SYSTEM_OUT"><PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] [%-5level] %c{36}:%L --- %m%n" /></Console><File name="file" fileName="${LOG_HOME}/myfile.log"><PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %l%c{36} - %m%n" /></File><RandomAccessFile name="accessFile" fileName="${LOG_HOME}/myAcclog.log"><PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %l%c{36} - %m%n" /></RandomAccessFile><RollingFile name="rollingFile" fileName="${LOG_HOME}/myrollog.log"filePattern="D:/logs/$${date:yyyy-MM-dd}/myrollog-%d{yyyyMM-dd-HH-mm}-%i.log"><ThresholdFilter level="debug" onMatch="ACCEPT" onMismatch="DENY" /><PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %l%c{36} - %msg%n" /><Policies><OnStartupTriggeringPolicy /><SizeBasedTriggeringPolicy size="10 MB" /><TimeBasedTriggeringPolicy /></Policies><DefaultRolloverStrategy max="30" /></RollingFile></Appenders><Loggers><Root level="trace"><AppenderRef ref="Console" /></Root></Loggers>
</Configuration>

3)JAVA代碼測試

import org.slf4j.LoggerFactory;public class LogTest {static org.slf4j.Logger logger = LoggerFactory.getLogger(LogTest.class);public static void main(String[] args) {logger.trace("trace level");logger.debug("debug level");logger.info("info level");logger.warn("warn level");logger.error("error level");}
}

參考:

  1. http://t.csdnimg.cn/lW60J
  2. https://time.geekbang.org/column/article/220307
  3. https://www.cnblogs.com/cxyyh/p/10633581.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/11238.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/11238.shtml
英文地址,請注明出處:http://en.pswp.cn/web/11238.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

JAVA 集合(單列集合)

集合框架 1.集合的特點 a.只能存儲引用數據類型的數據 b.長度可變 c.集合中有大量的方法,方便我們操作 2.分類: a.單列集合:一個元素就一個組成部分: list.add(“張三”) b.雙列集合:一個元素有兩部分構成: key 和 value map.put(“濤哥”,“金蓮”) -> key,value叫做鍵值…

Docker各版本的新特性

Docker 作為流行的容器化平臺&#xff0c;會定期發布新版本以引入新特性、改進和修復。根據提供的搜索結果&#xff0c;以下是一些 Docker 版本及其新特性的概覽&#xff1a; Docker Desktop v4.12 Containerd 的集成&#xff1a;更深入集成 containerd 以管理容器生命周期&a…

鎖和MVCC如何實現mysql的隔離級別

概述 MVCC解決讀的隔離性&#xff0c;加鎖解決寫的隔離性。 讀未提交 讀未提交&#xff0c;更新數據大概率使用的是獨享鎖吧。 讀已提交 在 Read Committed&#xff08;讀已提交&#xff09;隔離級別下&#xff0c;每次執行讀操作時都會生成一個新的 read view。這是因為在讀…

英譯漢早操練-(二十)

hello大家好&#xff0c;這篇跟隨十九&#xff0c;繼續真題學習。如果想看全部請返回到第十九篇。 英譯漢早操練-&#xff08;十九&#xff09;-CSDN博客 The political upheaval in Libya and elsewhere in North Africa has opened the way for thousands of new migrants to…

【C++學習第15天】STL

一、種類 vector&#xff1a;變長數組&#xff0c;倍增的思想。給數組申請空間所耗費的時間取決于申請次數&#xff0c;而不是申請空間的大小&#xff0c;即a[1]和a[10000]兩個數組的申請時間是基本一致的。pair<int, string>&#xff1a;存儲一個二元組&#xff0c;前后…

AI 圖像生成-環境配置

一、python環境安裝 Windows安裝Python&#xff08;圖解&#xff09; 二、CUDA安裝 CUDA安裝教程&#xff08;超詳細&#xff09;-CSDN博客 三、Git安裝 git安裝教程&#xff08;詳細版本&#xff09;-CSDN博客 四、啟動器安裝 這里安裝的是秋葉aaaki的安裝包 【AI繪畫…

【GlobalMapper精品教程】081:WGS84/CGCS2000轉Lambert投影

參考閱讀:ArcGIS實驗教程——實驗十:矢量數據投影變換 文章目錄 一、加載實驗數據二、設置輸出坐標系三、數據導出一、加載實驗數據 打開配套案例數據包中的data081.rar中的矢量數據,如下所示: 查看源坐標系:雙擊圖層的,圖層投影選項卡,數據的已有坐標系為WGS84地理坐標…

MySQL創建存儲過程函數

DDL CREATE TABLE student (id int(11) NOT NULL AUTO_INCREMENT COMMENT 學號,createDate datetime DEFAULT NULL,userName varchar(20) DEFAULT NULL,pwd varchar(36) DEFAULT NULL,phone varchar(11) DEFAULT NULL,age tinyint(3) unsigned DEFAULT NULL,sex char(2) DEFAU…

[初學rust] 05_ rust struct

rust struct 其實這也算復合類型&#xff0c;但是其他語言都有&#xff0c;所以抽取出來單獨看的時候會很簡單&#xff0c;更容易學 1. 定義結構體 結構體的定義和其他語言沒啥區別。 struct User {name: String,age: i32, }2. 創建實例 創建實例的過程就跟js類似 let us…

【3dmax筆記】021:對齊工具(快速對齊、法線對齊、對齊攝影機)

文章目錄 一、對齊二、快速對齊三、法線對齊四、對齊攝影機五、注意事項3dmax提供了對齊、快速對齊、法線對齊和對齊攝像機等對齊工具: 對齊工具選項: 下面進行一一講解。 一、對齊 快捷鍵為Alt+A,將當前選擇對象與目標對象進行對齊。 最大對最大:

【小筆記】neo4j用load csv指令導入數據

【小筆記】neo4j用load csv指令導入數據 背景 很久沒有用load CSV的方式導入過數據了因為它每次導入有數量限制&#xff08;印象中是1K還是1W&#xff09;&#xff0c;在企業中構建的圖譜往往都是大規模的&#xff0c;此時通常采用的是Neo4j-admin import方式。最近遇到了一些…

振弦式表面應變計怎么安裝

振弦式表面應變計是一種用于測量結構表面應變的高精度傳感器&#xff0c;廣泛應用于工程和科研領域。正確安裝振弦式表面應變計對于確保測量結果的準確性至關重要。以下是安裝振弦式表面應變計的步驟和注意事項&#xff1a; 1. 準備工作 在開始安裝前&#xff0c;需要準備以下工…

whisper之初步使用記錄

文章目錄 前言 一、whisper是什么&#xff1f; 二、使用步驟 1.安裝 2.python調用 3.識別效果評估 4.一點封裝 5.參考鏈接 總結 前言 隨著AI大模型的不斷發展&#xff0c;語音識別等周邊內容也再次引發關注&#xff0c;通過語音轉文字再與大模型交互&#xff0c;從而…

【Gitlab遠程訪問本地倉庫】Gitlab如何安裝配置并結合內網穿透實現遠程訪問本地倉庫進行管理

文章目錄 前言1. 下載Gitlab2. 安裝Gitlab3. 啟動Gitlab4. 安裝cpolar5. 創建隧道配置訪問地址6. 固定GitLab訪問地址6.1 保留二級子域名6.2 配置二級子域名 7. 測試訪問二級子域名 前言 GitLab 是一個用于倉庫管理系統的開源項目&#xff0c;使用Git作為代碼管理工具&#xf…

為什么質量工程師必學六西格瑪?突破職業發展的瓶頸?

在質量管理領域工作多年&#xff0c;你是否曾感受到事業發展的停滯不前&#xff1f;3年、5年的職業生涯&#xff0c;薪水依舊停留在每月5000-7000&#xff0c;而同行業的其他人卻能月入2-3萬&#xff0c;這種差距讓人不禁陷入深思。 問題究竟出在哪里&#xff1f;為什么我們的…

編譯OpenResty遇到找不到OpenSSL的解決辦法

以OpenResty-1.19.9.1為例 編輯openresty-1.19.9.1/build/nginx-1.19.9/auto/lib/openssl/conf CORE_INCS"$CORE_INCS $OPENSSL/.openssl/include" CORE_DEPS"$CORE_DEPS $OPENSSL/.openssl/include/openssl/ssl.h" CORE_LIBS"$CORE_LIBS $OPENSSL/.…

揭秘圖形編程 動靜接口如何助力 AGV 集成

在公司軟件開發團隊的辦公室里&#xff0c;陽光透過窗戶灑在排列整齊的辦公桌上。臥龍坐在辦公桌前&#xff0c;面前攤開一份內測報告&#xff0c;他的手指時不時地敲擊著桌面&#xff0c;流露出內心的煩躁。他抬起頭&#xff0c;眼神中透露出一絲困惑&#xff0c;看向正在文件…

調用函數實現數組的輸入排序插入與輸出

輸入一串數字&#xff0c;輸出排序插入后輸出最后的數字序列&#xff1b; 把主要步驟交給主函數&#xff0c;通過調用函數來實現整體的功能&#xff1a; 寫出主函數&#xff08;這里使用冒泡排序&#xff09;&#xff1a; int main(){int n;int a[10];cin>>n;inputa(a…

【網絡安全】【Frida實踐案例】某圖xx付費功能逆向分析(一)

文章目錄 一、目標應用二、環境三、步驟1、查看布局id2、用到的Log日志類信息3、嘗試hook VIP判斷方法 四、總結五、相關源碼 1、文章僅供學習參考&#xff0c;嚴禁非法使用&#xff01;如非法使用&#xff0c;而導致的一切后果&#xff0c;由使用者自負&#xff01; 2、禁止將…

【C++】string類常用函數用法總結

目錄 常用函數一覽 默認成員函數 與容量有關的函數 part 1 part 2 part 3 與訪問和遍歷有關的函數 與修改有關的函數 npos 與string相關的其它常用函數 常用非成員函數 getline和cin的區別 常用函數一覽 //默認成員函數 string();string(const char* s);string(si…