一、MDC的优点
1.
如果你的系统已经上线,突然有一天老板说我们增加一些用户数据到日志里分析一下,如果没有MDC我猜此时此刻你应该处于雪崩状态,MDC恰到好处的让你能够实现在日志上突如其来的一些需求。
2.
如果你是个代码洁癖,封装了公司LOG的操作,并且将处理线程跟踪日志号也封装了进去,但只有使用了你封装日志工具的部分才能打印跟踪日志号,其他部分(比如hibernate、mybatis、httpclient等等)日志都不会体现跟踪号。当然我们可以通过linux命令来绕过这些困扰。
3.
使代码简洁、日志风格统一。
二、进行看一看源码
package org.slf4j;
import java.util.Map;
import org.slf4j.helpers.NOPMDCAdapter;
import org.slf4j.helpers.Util;
import org.slf4j.impl.StaticMDCBinder;
import org.slf4j.spi.MDCAdapter;
public class MDC
{
static final String NULL_MDCA_URL = "http://www.slf4j.org/codes.html#null_MDCA";
static final String NO_STATIC_MDC_BINDER_URL = "http://www.slf4j.org/codes.html#no_static_mdc_binder";
static MDCAdapter mdcAdapter;
static
{
try
{
mdcAdapter = StaticMDCBinder.SINGLETON.getMDCA();
}
catch (NoClassDefFoundError ncde)
{
mdcAdapter = new NOPMDCAdapter();
String msg = ncde.getMessage();
if ((msg != null) && (msg.indexOf("StaticMDCBinder") != -1))
{
Util.report("Failed to load class \"org.slf4j.impl.StaticMDCBinder\".");
Util.report("Defaulting to no-operation MDCAdapter implementation.");
Util.report("See http://www.slf4j.org/codes.html#no_static_mdc_binder for further details.");
}
else
{
throw ncde;
}
}
catch (Exception e)
{
Util.report("MDC binding unsuccessful.", e);
}
}
public static void put(String key, String val)
throws IllegalArgumentException
{
if (key == null) {
throw new IllegalArgumentException("key parameter cannot be null");
}
if (mdcAdapter == null) {
throw new IllegalStateException("MDCAdapter cannot be null. See also http://www.slf4j.org/codes.html#null_MDCA");
}
mdcAdapter.put(key, val);
}
public static String get(String key)
throws IllegalArgumentException
{
if (key == null) {
throw new IllegalArgumentException("key parameter cannot be null");
}
if (mdcAdapter == null) {
throw new IllegalStateException("MDCAdapter cannot be null. See also http://www.slf4j.org/codes.html#null_MDCA");
}
return mdcAdapter.get(key);
}
public static void remove(String key)
throws IllegalArgumentException
{
if (key == null) {
throw new IllegalArgumentException("key parameter cannot be null");
}
if (mdcAdapter == null) {
throw new IllegalStateException("MDCAdapter cannot be null. See also http://www.slf4j.org/codes.html#null_MDCA");
}
mdcAdapter.remove(key);
}
public static void clear()
{
if (mdcAdapter == null) {
throw new IllegalStateException("MDCAdapter cannot be null. See also http://www.slf4j.org/codes.html#null_MDCA");
}
mdcAdapter.clear();
}
public static Map<String, String> getCopyOfContextMap()
{
if (mdcAdapter == null) {
throw new IllegalStateException("MDCAdapter cannot be null. See also http://www.slf4j.org/codes.html#null_MDCA");
}
return mdcAdapter.getCopyOfContextMap();
}
public static void setContextMap(Map<String, String> contextMap)
{
if (mdcAdapter == null) {
throw new IllegalStateException("MDCAdapter cannot be null. See also http://www.slf4j.org/codes.html#null_MDCA");
}
mdcAdapter.setContextMap(contextMap);
}
public static MDCAdapter getMDCAdapter()
{
return mdcAdapter;
}
}
三、使用MDC将日志信息存入日志文件中
1.首先导入maven的jar包
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.21</version>
</dependency>
2.编辑简单的demo
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
public class TestLog {
private static final Logger logger = LoggerFactory.getLogger(TestLog.class);
public static void main(String[] args) {
MDC.put("TESE_ID", String.valueOf(Thread.currentThread().getId()));
logger.info("测试日志中是否有当前自定义log");
}
}
3.配置自定义日志文件与格式logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration>
<configuration>
<appender name="Console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<!-- 自定义存入日志文件的格式 -->
<pattern>%d{yyyy-MM-dd HH:mm:ss} %-5level [%logger{16}] [%X{REQID}] [%X{SID}] [%X{UID}] %msg%n</pattern>
</encoder>
</appender>
<!-- 通过MDC.put()方法进行将打印的用户详细的操作信息放入日志文件中,可以很好的进行分析日志 -->
<appender name="FILE"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>/logs/logs.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- daily rollover -->
<!-- 日志存入的地点 -->
<fileNamePattern>/logs/logs.%d{yyyy-MM-dd}.log
</fileNamePattern>
<!-- 每6天清理一次日志文件 -->
<!-- keep 30 days' worth of history -->
<maxHistory>6</maxHistory>
</rollingPolicy>
<append>true</append>
<encoder>
<!-- 自定义存入日志文件的格式 -->
<pattern>%d{yyyy-MM-dd HH:mm:ss} %-5level [%logger{16}] [%X{REQID}] [%X{SID}] [%X{UID}] %msg%n</pattern>
</encoder>
</appender>
</configuration>