Log4jのJavaロギングまたはLogback NDCとMDC機能

NDCとMDCの違い

ログに使用されるJava実装フレームワーク多くの一般的に使用されるとのjava.util.loggingのlog4jとlogbackが、(ラップ実装)Apacheが達成オープンソースのlog4jログコンポーネントであり、ネイティブSLF4Jのlogbackが達成される(ネイティブインプリメンテーション)があります。Javaは、単純なログファサード(Java用のシンプルなロギングファサード)でSLF4JログSLF4Jのファサードを使用した場合、あなたは-APIをSLF4Jするために使用しなければならない注意しませんが、実装するのは簡単logbackであるので、他の追加の変換と移行ゾーンする必要があります消費、および実装SLF4Jのlog4jのを呼び出すために、それは呼び出し可能のモードSLF4J-APIのlog4jのへの適応を実現するために、アダプテーション層を必要とします。

完成した基本的な違いのロギングフレームワークの後、我々はNDCとMDCを見てください。

問題はすぐに問題の核心を見つけることができる場所を反映することができるようにするのlog4jまたはlogback、印刷ログかどうか、それは文脈情報(コンテキスト情報)を実施する必要があり、その後、店はこの情報の二つの重要なクラスは、(NDCですネストされた診断コンテキスト)およびMDC(マップされたDiagnositcコンテキスト)。

NDCは、使用コンテキストスタックメカニズム、別のスレッド、スレッドコンテキストのコピーから、親、子スレッドを保存します。その呼び出しは次のよう:

1.呼び出し
NDC.push(メッセージを)。

2.トップメッセージ削除
NDC.popを();

3. [すべてのニュース、呼び出しは、スレッドが終了する前に表示される必要があり、それ以外の場合は、メモリのオーバーフローにつながります。
NDC.remove();

4.テンプレートの出力は、小文字[%のX]を注意
log4j.appender.stdout.layout.ConversionPattern = [{Dの%MM-DD-YYYYのHH:MM:SSS}] [%のX]:%% N-M

MDCは、独立したスレッドの保存されたコンテキスト地図を使用して、親スレッドコンテキストからサブコピーをスレッド。その呼び出しは次のよう:

1.コンテキスト情報はに保存され
MDC.put(キー、値)。

2.コンテキストから提供される情報を取得
MDC.get(キー)。

3.コンテキスト明確に指定されたキー情報
MDC.remove(キー)。

4.すべてクリア
クリア()

出力テンプレート、資本を注意[%{X-キー}]
log4j.appender.consoleAppender.layout.ConversionPattern -4R%= [%のT] 5P%C%X% - %のM - %N-X-の%} {キー

最後に、ことに留意すべきです。

  • すべてのデータの%X地図を使用します
  • X {キー}がマップキーの出力値を指定%を使用
  • スタック出力の内容全体を使って%X

MDCの使用例

//MdcUtils.java
// import ...MdcConstants // 这个就是定义一个常量的类,定义了SERVER、SESSION_ID等
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;

public class MdcUtils {

    private final static Logger logger = LoggerFactory.getLogger(MdcUtils.class);

    private static void put(String key, Object value) {
        if (value != null) {
            String val = value.toString();
            if (StringUtils.isNoneBlank(key, val)) {
                MDC.put(key, val);
            }
        }
    }

    public static String getServer() {
        return MDC.get(MdcConstants.SERVER);
    }

    public static void putServer(String server) {
        put(MdcConstants.SERVER, server);
    }

    public static String getSessionId() {
        return MDC.get(MdcConstants.SESSION_ID);
    }

    public static void putSessionId(String sId) {
        put(MdcConstants.SESSION_ID, sId);
    }

    public static void clear() {
        MDC.clear();
        logger.debug("mdc clear done.");
    }
}

ツールクラスのMdcConstantsは、一定の定義されたクラス、定義されているサーバで、SESSION_IDのような、それはMDCのSLF4Jの方法を置くために電話を置くことです。その他のアナロジー。

のツールを使用するための特定の方法を見てください:

// MdcClearInterceptor.java
import ...MdcUtils; // 导入上面的工具类
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


public class MdcClearInterceptor extends HandlerInterceptorAdapter {
    @Override
    public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler)
                    throws Exception {
        MdcUtils.clear();
    }
}

インターセプタでは、SLF4J clearメソッドを呼び出すことで、このセッションコンテキストのログをクリアすることで明確な方法論ツールのカテゴリを、実行するためにafterConcurrentHandlingStartedメソッドを書き換えます。なぜafterConcurrentHandlingStartedがそれに近づく置きますか?これはおそらく実現さspringmvcがインターセプタからでした。

springmvc傍受HandlerInterceptorインタフェースは、三つの方法(下記のコード)、具体的にノートに記載される方法を定義します。

public interface HandlerInterceptor {  
    //在控制器方法调用前执行
    //返回值为是否中断,true,表示继续执行(下一个拦截器或处理器)
    //false则会中断后续的所有操作,所以我们需要使用response来响应请求
    boolean preHandle(  
            HttpServletRequest request, HttpServletResponse response,   
            Object handler)   
            throws Exception;  

    //在控制器方法调用后,解析视图前调用,我们可以对视图和模型做进一步渲染或修改
    void postHandle(  
            HttpServletRequest request, HttpServletResponse response,   
            Object handler, ModelAndView modelAndView)   
            throws Exception;  
    //整个请求完成,即视图渲染结束后调用,这个时候可以做些资源清理工作,或日志记录等
    void afterCompletion(  
            HttpServletRequest request, HttpServletResponse response,   
            Object handler, Exception ex)  
            throws Exception;  
}  

多くの場合、我々は唯一継承する必要があるため、唯一の上記の3つの方法が十分である必要があるHandlerInterceptorAdapterことを、HandlerInterceptorAdapterが間接的にHandlerInterceptorインターフェイスを達成し、三つの方法のためにHandlerInterceptor空の実装を行ったので、より簡単に私たち自身をカスタマイズします実装。

点からHandlerInterceptor、よりHandlerInterceptorAdapter実装afterConcurrentHandlingStarted()直接実装クラスから、それはHandlerInterceptorAdapter AsyncHandlerInterceptor直接継承されたインタフェースから、AsyncHandlerInterceptor HandlerInterceptor、非同期リクエストを処理するための新しいafterConcurrentHandlingStarted()メソッドを追加し、コントローラ非同期リクエストメソッドがする時間がありますトリガー方法、preHandleをサポートする非同期要求は、その後、afterConcurrentHandlingStartedを実行したとき。非同期スレッドの完了後に実行preHandle、postHandle、afterCompletion。

それの割り当ては、MDCUtils.put()メソッドを呼び出すために何であるフィールドからログを使用する可能性があるものについては?一般的に、我々はRequestHandlerInterceptorを達成する、治療はpreHandlerメソッド内のフィールドをログに記録することができます。次のように:

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
        throws Exception {
    if (DispatcherType.ASYNC.equals(request.getDispatcherType())) {
        return true;
    }
    
    // 开始保存信息到日志上下文
    MdcUtils.putServer(request.getServerName());
    String sId = request.getHeader(HeaderConstants.SESSION_ID);
    MdcUtils.putSessionId(sId);

    if (sessionWhiteList.contains(request.getPathInfo())) {
        return true;
    }

    // TODO 处理其他业务
}

終了していない、今見、我々は達成2つのカスタムインターセプタを持っています。どのように私たちにそれを印刷します正しいログによると、使用するには?必ずしも、インターセプタは、インターセプタ複数の、インターセプターは、AOPの実行シーケンスと同様鎖を形成する場合、最初の事前定義された最初のインターセプトは、傍受を傍受登録ポストと終了を行う、ためである(afterCompletion)実行後。

曽我は、我々は再び私たちの情報が原因afterConcurrentHandlingStarted()メソッドは非同期要求がトリガーが必要です、MDC(DispatcherServletの中インターセプター構成)に書かれているので、私たちはウェブを必要とする、いくつかの役に立たない情報に最後の要求をクリアする必要があります。 XML構成はDispatchServlet増大<async-supported>true</async-supported>構成を。

<mvc:interceptors>
    <bean class="com.xxx.handler.MdcClearInterceptor"/>
    <bean class="com.xxx.handler.RequestContextInterceptor"/>
</mvc:interceptors>

それとも、この:

<mvc:interceptors>
    <!-- 前置拦截器 -->
    <mvc:interceptor>
        <!-- 这里面还以增加一些拦截条件-->
        <!--<mvc:exclude-mapping path="/user/logout"/>-->
        <!-- 用户退出登录请求 -->
        <!-- <mvc:exclude-mapping path="/home/"/> -->
        <!--在home中定义了无须登录的方法请求,直接过滤拦截-->
        <!-- <mvc:mapping path="/**"/>-->
        <bean class="com.xxx.handler.MdcClearInterceptor"/>
    </mvc:interceptor>

    <!-- 后置拦截器 -->
    <mvc:interceptor>
        <bean class="com.xxx.handler.RequestContextInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>

本論文では、出発「オープンマインド」署名、複製、ソースを明記してくださいする前に個人のブログ、複製、必ずご覧ください。

タオの古代マスターズ、微妙な玄トン、深い認識できません。:誰受ける強いので、フー魏は認識できない
ゆうXiの冬渋川場合、まだ西、西ヤン乗客あれば、パークロンドン西、西場合Ruoguクァン、Xiは混合リリースのフアン西若-ビング、場合隣人を恐れますその濁度場合。
練習は静けさ許晴に雲を作りますか?練習は徐盛を移動することが安全なのでしょうか?
ポールはこの道の黒字を望んでいません。夫は、利益は、それが新しいと広々なる可能性はありません。

私のマイクロチャンネル公衆番号に注意してください:雨がピアノを弾くようなものです、感謝♪(・ω・)テクノ

マイクロチャネルの二次元コード

おすすめ

転載: www.cnblogs.com/joyven/p/11776524.html