第8章 集成Log4J日誌

開心一笑

【牛頓一輩子沒結婚,他創立牛頓三定律,萬有引力定律,張三丰一輩子沒結婚,活到了200多歲,在一百二十多歲創造了太極拳,威震江湖!孫悟空一輩子沒結婚,活了不知道多少歲,大鬧過天宮,闖過龍宮,鬧過地府,最後成了鬥戰勝佛…不用我多說了吧 ,都TMD別惹我,我也是單身狗!】

8.1 Log4J介紹

8.1.1 Log4J概述

Log4j是Apache下的一個開源項目,通過使用Log4j,我們可以將日誌信息打印到控制檯、文件等。我們也可以控制每一條日誌的輸出格式,通過定義每一條日誌信息的級別,我們能夠更加細緻地控制日誌的生成過程。
在應用程序中添加日誌記錄有三個目的:
1) 監視代碼中變量的變化情況,週期性的記錄到文件中供其它應用進行統計分析工作。
2) 跟蹤代碼運行時軌跡,作爲日後審計的依據。
3) 擔當集成開發環境中的調試器的作用,向文件或控制檯打印代碼的調試信息。
Log4j中有三個主要的組件,它們分別是:Loggers(記錄器),Appenders (輸出源)和Layouts(佈局),這三個組件可以簡單的理解爲日誌類別,日誌要輸出的地方和日誌以何種形式輸出。Log4J原理如圖8-1所示。
在這裏插入圖片描述
圖8-1 Log4J日誌框架簡單原理圖
Loggers(記錄器):Loggers組件被分爲七個級別:all、debug、info、warn、error、fatal、off。這七個級別是有優先級的:all<debug< info< warn< error< fatal<off,分別用來指定這條日誌信息的重要程度。 Log4j有一個規則:只輸出級別不低於設定級別的日誌信息。假設Loggers級別設定爲info,則info、warn、error和fatal級別的日誌信息都會輸出,而級別比info低的debug則不會輸出。Log4j允許開發人員定義多個Logger,每個Logger擁有自己的名字,Logger之間通過名字來表明隸屬關係。
Appenders(輸出源):Log4j日誌系統允許把日誌輸出到不同的地方,如控制檯(Console)、文件(Files)等,可以根據天數或者文件大小產生新的文件,可以以流的形式發送到其它地方等等。
Layouts(佈局):Layout的作用是控制Log信息的輸出方式,也就是格式化輸出的信息。
Log4j支持兩種配置文件格式,一種是XML格式的文件,一種是Java特性文件 log4j2.properties (鍵 = 值),properties文件簡單易讀,而XML文件可以配置更多的功能(比如過濾),沒有好壞,能夠融會貫通就是最好的。具體的XML配置如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
        </Console>
    </Appenders>
    <Loggers>
        <Root level="debug">
            <AppenderRef ref="Console" />
        </Root>
    </Loggers>
</Configuration>

8.2 集成Log4j2

8.2.1 引入依賴

在Spring Boot中集成Log4j2,首先需要在pom.xml文件中引入所需的依賴,具體代碼如下:

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

Spring Boot默認使用Logback日誌框架來記錄日誌,並用INFO級別輸出到控制檯,所以我們在引入Log4j2之前,需要先排除該包的依賴,再引入Log4j2的依賴。具體做法就是找到pom.xml文件中的spring-boot-starter-web依賴,使用exclusion標籤排除Logback,具體排除Logback依賴的代碼如下:

<dependency>
		<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
			<exclusions>
				<!-- 排查Spring Boot默認日誌 -->
				<exclusion>
					<groupId>org.springframework.boot</groupId>
					<artifactId>spring-boot-starter-logging</artifactId>
			</exclusion>
		</exclusions>
	</dependency>

8.2.2 添加Log4J配置

在8.1節當中,我們已經講過,Log4j2支持兩種配置文件格式,一種是XML格式的文件,一種是properties文件的格式。這裏我們使用XML格式配置Log4j2,properties格式可以作爲大家自學任務。使用XML格式配置很簡單,我們只需要在application.properties文件中添加如下的配置信息:

###log4j配置
logging.config=classpath:log4j2.xml

配置完成之後,Spring Boot就會幫我們在classpath路徑下查找log4j2.xml文件,所以最後一步,我們只需要配置好log4j2.xml文件即可。

8.2.3 創建log4j2.xml文件

application.properties配置完成之後,我們在目錄/src/main/resources目錄下新建空的日誌配置文件log4j2.xml。具體代碼如下:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <appenders>
        
    </appenders>
    <loggers>
        <root level="all">
			
        </root>
    </loggers>
</Configuration>

8.3 使用Log4J記錄日誌

8.3.1 打印到控制檯

現在我們需要把日誌打印到控制檯,所以需要往log4j2.xml配置文件添加相關的配置,具體代碼如下:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <appenders>
        <Console name="Console" target="SYSTEM_OUT">
			<!-- 指定日誌的輸出格式 -->
            <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
        </Console>
    </appenders>
    <loggers>
        <root level="all">
			<!-- 控制檯輸出 -->
            <appender-ref ref="Console"/>
        </root>
    </loggers>
</Configuration>

<Console/ >:指定控制檯輸出。
< PatternLayout />:控制日誌的輸出格式。
Spring Boot集成Log4j日誌完成之後,在6.2.2和7.3.1節中,我們已經開發好AyUserListener監聽器,但是使用System.out.println來打印信息,這是一種非常不合理的方式,現在我們把Logger 類引入到AyUserListener.java監聽器中,同時把System.out.println相關代碼註釋掉,改成用日誌方式記錄信息。這樣,在項目啓動過程中,調用上下文初始化和銷燬方法的時候,就會記錄日誌到開發工具控制檯或者日誌文件中。AyUserListener具體代碼如下:

/**
 * 描述:監聽器
 * @author Ay
 * @date   2017/11/4
 */
@WebListener
public class AyUserListener implements ServletContextListener {
	   //省略代碼
	   //需要添加的代碼
    Logger logger = LogManager.getLogger(this.getClass());
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        //查詢數據庫所有的用戶
        List<AyUser> ayUserList =  ayUserService.findAll();
        //清除緩存中的用戶數據
        redisTemplate.delete(ALL_USER);
        //存放到redis緩存中
        redisTemplate.opsForList().leftPushAll(ALL_USER, ayUserList);
        //真實項目中需要註釋掉
        List<AyUser> queryUserList = redisTemplate.opsForList().range(ALL_USER, 0, -1);
        //System.out.println("緩存中目前的用戶數有:" + queryUserList.size() + " 人");
        //System.out.println("ServletContext上下文初始化");
        logger.info("ServletContext上下文初始化");
        logger.info("緩存中目前的用戶數有:" + queryUserList.size() + " 人");
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        //System.out.println("ServletContext上下文銷燬");
        logger.info("ServletContext上下文銷燬");
    }
}

8.3.2 記錄到文件

在8.3.1節中,日誌只是被打印到控制檯中,當項目真正被上線之後,是沒有控制檯這個概念的,上線環境中,項目的日誌都是被記錄到文件中的。所以我們繼續在log4j2.xml配置文件中添加相關配置,使日誌可以被打印到文件中,具體代碼如下:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <!-- 設置日誌輸出的格式 -->
            <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
        </Console>
        <RollingFile name="RollingFileInfo" fileName="D:/info.log"
                     filePattern="D:/$${date:yyyy-MM}/info-%d{yyyy-MM-dd}-%i.log">
            <Filters>
                <ThresholdFilter level="INFO"/>
            </Filters>
            <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
            <Policies>
                <TimeBasedTriggeringPolicy/>
                <SizeBasedTriggeringPolicy size="100 MB"/>
            </Policies>
        </RollingFile>
    </appenders>

    <loggers>
        <root level="all">
            <appender-ref ref="Console"/>
            <appender-ref ref="RollingFileInfo"/>
        </root>
    </loggers>

</Configuration>

< RollingFile>標籤:fileName用於定義日誌的數據路徑,如D:/info.log。filePattern定義日誌的匹配方式。
< Filters>標籤:日誌過濾策略,標籤用於指定日誌信息的最低輸出級別,默認爲DEBUG,
現在我們修改3.2.3節當中AyUserServiceImpl類的刪除方法delete,我們希望刪除用戶這個操作可以被記錄到日誌文件中,AyUserServiceImpl類代碼具體的修改點如下:

/**
 * 描述:用戶服務層實現類
 * @author 阿毅
 * @date   2017/10/14
 */
//@Transactional
@Service
public class AyUserServiceImpl implements AyUserService {
    //省略代碼
    //需要添加的代碼
    Logger logger = LogManager.getLogger(this.getClass());

    @Override
    public void delete(String id) {
        ayUserRepository.delete(id);
		 //需要添加的代碼
        logger.info("userId:" + id + "用戶被刪除");
    }

    //省略代碼
}

8.3.3 測試

代碼開發完成之後,接下來就是測試工作了。我們重新啓動項目,啓動之前,記得打開Redis服務器,因爲之前的章節,我們已經在Spring Boot中整合了Redis。項目重啓的過程中,我們可以在Intellij IDEA控制檯中看到如圖8-2所示的信息。同時,我們可以到D盤查看日誌文件info.log,在日誌文件中按住Ctrl + F,查詢到和圖8-2所示一樣的信息。

在這裏插入圖片描述
圖8-3 redis斷點調試界面
接着,我們再測試下,刪除用戶的時候,日誌是否可以打印到控制檯或者記錄到日誌文件中。我們在測試類MySpringBootApplicationTests下添加測試用例,具體代碼如下:

@RunWith(SpringRunner.class)
@SpringBootTest
public class MySpringBootApplicationTests {
   //省略代碼
	Logger logger = LogManager.getLogger(this.getClass());

	  @Test
	  public void testLog4j(){
		  ayUserService.delete("4");
		  logger.info("delete success!!!");
	}
}

在數據庫ay_test表中存在4條數據,如圖8-3所示。運行單元測試方法testLog4j,如果同樣可以在Intellij IDEA控制檯或者D盤的info.log文件中打印如圖8-4所示信息,證明Spring Boot整合Log4j以及在Spring Boot中運用Log4j成功。

在這裏插入圖片描述
圖8-3 redis斷點調試界面 圖8-4 redis斷點調試界面

啓動項目的時候,記得啓動Redis服務器,否則會報錯。


讀書感悟

來自《女士品茶》

  • 有些讀者會說:這絕對是喫飽了撐的!他們會問:“不管這位女士能否分辨兩種飲品,這件事有什麼意義呢?”“這個問題一點兒也不重要,對科學也沒有益處,”他們嘲笑道,“這些聰明人應該把他們的頭腦用在能夠造福人類的事情上。” 不幸的是,不管普通大衆如何看待科學及其影響,根據我的經驗,大多數科學家之所以投入到研究當中,是因爲他們對結果感興趣,並能從工作中獲得知識性的樂趣。優秀的科學家很少會考慮他們的工作是否具有重要意義。回到劍橋那個陽光明媚的夏日午後。女士有可能猜中飲品的混合方式,也有可能猜錯。這件事的樂趣在於找出一種方法判斷她的說法是否正確。在尖髯男子的指導下,他們開始討論如何驗證這種判斷。

經典故事

祖父用紙給我做過一條長龍。長龍腹腔的空隙僅僅只能容納幾隻蝗蟲,投放進去,它們都在裏面死了,無一倖免!祖父說:“蝗蟲性子太躁,除了掙扎,它們沒想過用嘴巴去咬破長龍,也不知道一直向前可以從另一端爬出來。因而,儘管它有鐵鉗般的嘴殼和鋸齒一般的大腿,也無濟於事。”當祖父把幾隻同樣大小的青蟲從龍頭放進去,然後關上龍頭,奇蹟出現了:僅僅幾分鐘,小青蟲們就一一地從龍尾爬了出來。

【命運一直藏匿在我們的思想裏。許多人走不出人生各個不同階段或大或小的陰影,並非因爲他們天生的個人條件比別人要差多遠,而是因爲他們沒有思想要將陰影紙龍咬破,也沒有耐心慢慢地找準一個方向,一步步地向前,直到眼前出現新的洞天。】


大神文章


其他

如果有帶給你一絲絲小快樂,就讓快樂繼續傳遞下去,歡迎鼓勵,點贊、頂、歡迎留下寶貴的意見、多謝支持!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章