NDC和MDC是log4j用於存儲應用程序的上下文信息(context infomation),從而便於在log中使用這些上下文信息。
NDC採用了一個類似棧的機制來push存儲上下文信息,每一個線程都獨立地儲存上下文信息。比如說一個servlet就可以針對每一個request創建對應的NDC,儲存客戶端地址等等信息。相關的信息使用NDC.push(message);
在log的時候將信息輸出。在相應的PatternLayout中使用”%x”來輸出存儲的上下文信息
例如:
String remoteAddr = request.getRemoteAddr();
NDC.push(remoteAddr);
在log4j.properties文件中作如下的配置即可
log4j.appender.console.layout.ConversionPattern=%-d{yyyy/MM/dd HH:mm:ss,SSS} [%X] -[%c]-[%p] %m%n
MDC內部使用了類似map的機制來存儲信息,相對應的方法,MDC.put(key, value);在配置PatternLayout的時候使用:%x{key}來輸出對應的value
例如:
String remoteAddr = request.getRemoteAddr();
MDC.put("ip", remoteAddr);
在log4j.properties文件中作如下的配置即可
log4j.appender.console.layout.ConversionPattern=%-d{yyyy/MM/dd HH:mm:ss,SSS} [%X{ip}] -[%c]-[%p] %m%n
如果在項目中有過濾器,你可以把獲取ip 的方法直接定義在過濾器中,然後在配置文件中配置獲取ip的顯示就可以了
=====================================================================
下面附上MDC應用代碼:
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object arg2) throws Exception {
String user = request.getSession().getAttribute(Constants.SESN_USR_NAME)+"";
MDC.put("user", StringUtils.isBlank(user)?"":user );
if (LOG.isDebugEnabled()){
long beginTime = System.currentTimeMillis();//1、開始時間
startTimeThreadLocal.set(beginTime); //線程綁定變量(該數據只有當前請求的線程可見)
LOG.debug("開始計時: {} URI: {}", new SimpleDateFormat("hh:mm:ss.SSS").format(beginTime), request.getRequestURI());
}
return true;
}
## 日誌配置
log4j.appender.E.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss,SSS} -[%p] %X{user} method:[%l (%rms)] - %m%n
用法還是很簡單的。
這樣在程序裡可以不用在打印日誌的時候加上用戶了。同樣存在一些IP等的需求也可以這樣做。
能夠減少不少工作量,也能避免大家忘記打印用戶name或者其他相關信息。
閱讀更多 JAVA破局之路 的文章