Spring Boot 日志概念及使用詳解
一、為什么要學(xué)習(xí)日志
日志對我們來說并不陌生,從JavaSE部分,我們就在使用 System.out.print 來打印日志了.通過打
印日志來發(fā)現(xiàn)和定位問題,或者根據(jù)日志來分析程序的運行過程.在 Spring 的學(xué)習(xí)中,也經(jīng)常根據(jù)控制臺的日志來分析和定位問題.
隨著項目的復(fù)雜度提升,我們對日志的打印也有了更高的需求,而不僅僅是定位排查問題.
比如需要記錄一些用戶的操作記錄(一些審計公司會要求),也可能需要使用日志來記錄用戶的一些喜好,把日志持久化,后續(xù)進行數(shù)據(jù)分析等.但是 System.out.print 不能很好的滿足我們的需求,我們就需要使用一些專門日志框架(專業(yè)的事情交給專業(yè)的人去做).
二、認識日志格式

1??時間日期:精確到毫秒
2??日志級別:ERROR,WARN,INFO,DEBUG或TRACE
3??進程 ID
4??線程名
5??Logger 名(通常使用源代碼的類名)
6??日志內(nèi)容
三、日志使用
SpringBoot 內(nèi)置了日志框架 Slf4j ,我們可以直接在程序中調(diào)用 Slf4j 來輸出日志
打印日志
步驟
• 在程序中得到日志對象.
需要使用志工廠 LoggerFactory
private static Logger logger = LoggerFactory.getLogger(CaptchaController.class);
LoggerFactory.getLogger 需要傳遞?個參數(shù), 標識這個日志的名稱. 這樣可以更清晰的知道是哪個類輸出的日志. 當(dāng)有問題時, 可以更方便直觀的定位到問題類
• 使用日志對象輸出要打印的內(nèi)容.
日志對象的打印方法有很多種,我們可以先使用 info() 方法來輸出日志
logger.info("Logger生成驗證碼: " + code);日志框架介紹

SLF4J不同于其他日志框架, 它不是一個真正的日志實現(xiàn), 而是一個抽象層, 對日志框架制定的一種規(guī)范, 標準, 接口. 所有SLF4J并不能獨立使用, 需要和具體的日志框架配合使用.
門面模式(外觀模式)
SLF4J是門面模式的典型應(yīng)用(但不僅僅使用了門面模式).
門面模式(Facade Pattern)又稱為外觀模式,提供了一個統(tǒng)一的接口,用來訪問子系統(tǒng)中的一群接口.其主要特征是定義了一個高層接口,讓子系統(tǒng)更容易使用.


門面模式主要包含2種角色:
外觀角色(Facade):也稱門面角色,系統(tǒng)對外的統(tǒng)一接口.
子系統(tǒng)角色(SubSystem):可以同時有一個或多個SubSystem.每個SubSytem都不是一個單獨的類,
而是一個類的集合.SubSystem并不知道Facade的存在,對于SubSystem而言,F(xiàn)acade只是另一個客戶端而已(即Facade對SubSystem透明)


門面模式的實現(xiàn)
場景: 回家, 我們會開各個屋的燈. 離開家時, 會關(guān)閉各個屋的燈. 如果家里設(shè)置?個總開關(guān), 來控制整個屋的燈就會很方便.
沒建門面前
package com.example.demo.facade;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public interface Light {
void on();
void off();
}
public HallLight implements Light {
private static Logger logger = LoggerFactory.getLogger(HallLight.class);
@Override
public void on() {
logger.info("打開走廊燈");
}
@Override
public void off() {
logger.info("關(guān)閉走廊燈");
}
}
public LivingRoomLight implements Light {
private static Logger logger = LoggerFactory.getLogger(LivingRoomLight.class);
@Override
public void on() {
logger.info("打開客廳燈");
}
@Override
public void off() {
logger.info("關(guān)閉客廳燈");
}
}
public BedRoomLight implements Light {
private static Logger logger = LoggerFactory.getLogger(BedRoomLight.class);
@Override
public void on() {
logger.info("打開臥室燈");
}
@Override
public void off() {
logger.info("關(guān)閉臥室燈");
}
}
public class Main {
public static void main(String[] args) {
HallLight hallLight = new HallLight();
LivingRoomLight livingRoomLight = new LivingRoomLight();
BedRoomLight bedRoomLight = new BedRoomLight();
hallLight.on();
livingRoomLight.on();
bedRoomLight.on();
}
}我們使用門面模式的實現(xiàn)
package com.example.demo.facade;
public class LightFacade {
void lightOn() {
HallLight hallLight = new HallLight();
LivingRoomLight livingRoomLight = new LivingRoomLight();
BedRoomLight bedRoomLight = new BedRoomLight();
hallLight.on();
livingRoomLight.on();
bedRoomLight.on();
}
void lightOff() {
HallLight hallLight = new HallLight();
LivingRoomLight livingRoomLight = new LivingRoomLight();
BedRoomLight bedRoomLight = new BedRoomLight();
hallLight.off();
livingRoomLight.off();
bedRoomLight.off();
}
}package com.example.demo.facade;
public class Main {
public static void main(String[] args) {
LightFacade lightFacade = new LightFacade();
lightFacade.lightOn();
lightFacade.lightOff();
}
}門面模式的優(yōu)點
●減少了系統(tǒng)的相互依賴,實現(xiàn)了客戶端與子系統(tǒng)的耦合關(guān)系,這使得子系統(tǒng)的變化不會影響到調(diào)用它的客戶端.
●提高了靈活性,簡化了客戶端對子系統(tǒng)的使用難度,客戶端無需關(guān)心子系統(tǒng)的具體實現(xiàn)方式,而只需要和門面對象交互即可.
●提高了安全性,可以靈活設(shè)定訪問權(quán)限,不在門面對象中開通方法,就無法訪問.
SLF4J 就是其他日志框架的門面. SLF4J 可以理解為是提供日志服務(wù)的統(tǒng)一API接口, 并不涉及到具體的日志邏輯實現(xiàn).
四、日志級別
日志級別代表著日志信息對應(yīng)問題的嚴重性, 為了更快的篩選符合目標的日志信息.
日志級別分類
日志的級別從高到低依次為:FATAL、ERROR、WARN、INFO、DEBUG、TRACE
??FATAL: 致命信息,表示需要立即被處理的系統(tǒng)級錯誤.
??ERROR: 錯誤信息,級別較高的錯誤日志信息,但仍然不影響系統(tǒng)的繼續(xù)運行.
??WARN: 警告信息,不影響使用,但需要注意的問題.
??INFO: 普通信息,用于記錄應(yīng)用程序正常運行時的一些信息,例如系統(tǒng)啟動完成、請求處理完成等.
??DEBUG: 調(diào)試信息,需要調(diào)試時候的關(guān)鍵信息打印.
??TRACE: 追蹤信息,比 DEBUG 更細粒度的信息事件(除非有特殊用意,否則請使用 DEBUG級別替代).

日志級別的使用
package com.example.demo.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/logger")
@RestController
public class LoggerLevelController {
private static Logger logger = LoggerFactory.getLogger(LoggerLevelController.class);
@RequestMapping("/print")
public String print() {
logger.trace("trace級別日志......");
logger.debug("debug級別日志......");
logger.info("info級別日志......");
logger.warn("warn級別日志......");
logger.error("error級別日志......");
return "打印日志";
}
}

結(jié)果發(fā)現(xiàn), 只打印了info, warn和error級別的日志.
這與日志級別的配置有關(guān), 日志的輸出級別默認是 info 級別, 所以只會打印大于等于此級別的日志, 也就是 info, warn和error.
日志配置
配置日志級別
logging:
level:
root: debug
日志級別也可以分類來設(shè)置
logging:
level:
root: info
com:
example:
demo:
controller: trace
日志持久化
以上的日志都是輸出在控制臺上的, 然日在線上環(huán)境中, 我們需要把日志保存下來, 以便出現(xiàn)問題之后追溯問題. 把日志保存下來就叫持久化.
日志持久化有兩種方式

1??配置日志文件名
logging:
file:
name: logger/springboot.log后?可以跟絕對路徑或者相對路徑

2??配置日志的存儲目錄
logging:
file:
path: D:/temp
logging:
file:
path: D:/temp/aaa/springboot.log
這種方式只能設(shè)置日志的路徑, 文件名為固定的 spring.log
??logging.file.name 和 logging.file.path 兩個都配置的情況下, 只生效其一, 以 logging.file.name 為準.
配置日志文件分割
如果我們的日志都放在一個文件中, 隨著項目的運行, 日志文件會越來越大, 需要對日志文件進行分割.
logging:
file:
#path: D:/temp/aaa/springboot.log
name: logger/springboot.log
logback:
rollingpolicy:
max-file-size: 1KB
file-name-pattern: ${LOG_FILE}.%d{yyyy-MM-dd}.%i
1.日志文件超過 1KB 就分割(設(shè)置 1KB 是為了更好展示.企業(yè)開發(fā)通常設(shè)置為200M,500M等,此處沒有明確標準)
2.分割后的日志文件名為:日志名.日期.索引
五、更簡單的日志輸出
每次都使用 LoggerFactory.getLogger(xxx.class) 很繁瑣, 且每個類都添加一遍, lombok 給我們提供了?種更簡單的方式.
1??添加 lombok 框架支持
2??使用 @Slf4j 注解輸出日志
lombok 提供的 @Slf4j 會幫我們提供?個日志對象 log, 我們直接使用就可以.
package com.example.demo.controller;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RequestMapping("/logger2")
@RestController
public class LoggerLevelController2 {
//private static Logger logger = LoggerFactory.getLogger(LoggerLevelController2.class);
@RequestMapping("/print")
public String print() {
log.trace("trace級別日志......");
log.debug("debug級別日志......");
log.info("info級別日志......");
log.warn("warn級別日志......");
log.error("error級別日志......");
return "打印日志";
}
}到此這篇關(guān)于Spring Boot 日志的文章就介紹到這了,更多相關(guān)Spring Boot 日志內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java中LambdaQueryWrapper設(shè)置自定義排序代碼示例
這篇文章主要給大家介紹了關(guān)于Java中LambdaQueryWrapper設(shè)置自定義排序的相關(guān)資料,lambdaquerywrapper是MyBatis-Plus框架中的一個查詢條件構(gòu)造器,它可以用于構(gòu)建自定義的查詢條件,需要的朋友可以參考下2023-12-12
Spring?Boot?集成Elasticsearch模塊實現(xiàn)簡單查詢功能
本文講解了Spring?Boot集成Elasticsearch采用的是ES模板的方式實現(xiàn)基礎(chǔ)查詢,本文結(jié)合實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧2022-06-06
Java while和do...while循環(huán)的使用方式
文章對比Java while與do-while循環(huán)的核心機制、語法差異、適用場景及錯誤防范,強調(diào)do-while至少執(zhí)行一次的特點,指出語法規(guī)范(如結(jié)尾分號)和性能優(yōu)化要點,并提及Java17模式匹配對循環(huán)的擴展支持2025-07-07
java簡單實現(xiàn)用語音讀txt文檔方法總結(jié)
在本篇文章里小編給大家整理了關(guān)于java簡單實現(xiàn)用語音讀txt文檔的詳細方法總結(jié),有需要的朋友們參考下。2019-06-06

