系統中使用log4j2做爲日誌系統,然而在高併發的狀況下,屢次請求的日誌參雜在一塊兒,要跟蹤某個用戶一次的請求操做全部日誌是很麻煩的。幸運的是log4j中有相應的解決方案。html
NDC(Nested Diagnostic Context)和MDC(Mapped Diagnostic Context)是log4j種很是有用的兩個類,它們用於存儲應用程序的上下文信息(context infomation),從而便於在log中使用這些上下文信息。NDC採用了一個相似棧的機制來push和pop上下文信息,每個線程都獨立地儲存上下文信息。好比說一個servlet就能夠針對每個request建立對應的NDC,儲存客戶端地址等等信息。MDC和NDC很是類似,所不一樣的是MDC內部使用了相似map的機制來存儲信息,上下文信息也是每一個線程獨立地儲存,所不一樣的是信息都是以它們的key值存儲在」map」中。java
NDC和MDC的原理是用了java的ThreadLocal類。能夠針對不一樣線程存儲信息。可是今天在log4j2上使用時發現沒有找到NDC和MDC。查找官方文檔,原來是換成了ThreadContext。操做也挺簡單:apache
在官方文檔的Pattern Layout章節的Patterns子章節下,能夠看到對於%X佔位符的描述。併發
描述中提到,存入ThreadContext的映射關係,可以輸出到對應的X佔位符中,這正好是顯示登陸者信息的理想實現方式。app
官方文檔地址:Log4j 2 API Thread Context高併發
PatternLayout.pattern
格式,追加[%X{userName}]
佔位符<PatternLayout pattern="%d %-5p [%t][%X{userName}] %C{2} (%F:%L) - %m%n"/>
2.追加Java代碼,登陸時,往ThreadContext存入映射關係,這裏爲了方便演示,存了固定值post
ThreadContext.put("userName","kevin");
3.追加Java代碼,在退出登陸後,清除ThreadContext的映射關係線程
ThreadContext.clear();
至此,實現完畢。日誌
2019-10-31 10:01:37,932 INFO [http-nio-8082-exec-4][kevin] aspect.LogAspect (WareLogAspect.java:56)
參考:
-【https://www.wangzhengzhen.com】
-【https://spldeolin.com/posts/log4j2-mdc/?tdsourcetag=s_pctim_aiomsg】code