1. 程式人生 > >controller層統一攔截進行日誌處理

controller層統一攔截進行日誌處理

uuid final asp end sna ogg long lan tostring

前言

在項目中添加統一日誌時,我們往往會用到aop進行切面處理,常用在controller層添加切面,以處理請求和返回的各項參數數據。

使用切面進行日誌處理

下面我們就看一個例子說明基本的使用方式:

package com.ding.test.core.aspect;

import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.MDC; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestAttributes; import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes; @Aspect @Component public class LogAspect { private final static Logger LOGGER = LoggerFactory.getLogger(LogAspect.class);    //定義切點 @Pointcut("execution(* com.ding..controller.*.*(..))") public void printLog() { }
/** * 會話ID */ private final static String SESSION_TOKEN_KEY = "sessionTokenId"; @Around("printLog()") private Object doAround(ProceedingJoinPoint pjp) throws Throwable { long startTime = System.currentTimeMillis(); String token = java.util.UUID.randomUUID().toString().replaceAll("-", "").toUpperCase(); MDC. put(SESSION_TOKEN_KEY, token); RequestAttributes ra = RequestContextHolder.getRequestAttributes(); ServletRequestAttributes sra = (ServletRequestAttributes) ra; HttpServletRequest request = sra.getRequest(); // 獲取請求相關信息 String url = request.getRequestURL().toString(); String method = request.getMethod(); String uri = request.getRequestURI(); String queryString = request.getQueryString(); // 獲取調用方法相信 Signature signature = pjp.getSignature(); String className = signature.getDeclaringTypeName(); String methodName = signature.getName();     //這裏定義log輸出的內容,前面是內容格式,{}按照順序被替換為後面參數的具體值 LOGGER.info("請求開始, {}#{}() URI: {}, method: {}, URL: {}, params: {}", className, methodName, uri, method, url, queryString); //result的值就是被攔截方法的返回值 try { //proceed方法是調用實際所攔截的controller中的方法,這裏的result為調用方法後的返回值 Object result = pjp.proceed(); long endTime = System.currentTimeMillis(); //定義請求結束時的返回數據,包括調用時間、返回值結果等 LOGGER.info("請求結束, {}#{}(), URI: {}, method: {}, URL: {}, time: {}ms, result: {} ", className, methodName, uri, method, url, (endTime - startTime), result); return result; } catch (Exception e) { long endTime = System.currentTimeMillis(); LOGGER.error("請求出錯, {}#{}(), URI: {}, method: {}, URL: {}, time: {}ms", className, methodName, uri, method, url, (endTime - startTime), e); throw e; }finally { MDC. remove(SESSION_TOKEN_KEY); } } }

本來spring就自帶一套aop實現,我們直接使用此實現即可,本來使用aop還需要定義一些xml文件,但由於我們使用的是spring-boot框架,這一步就省略掉了。也就是說,在spring-boot中,我們可以直接使用aop而不需要任何的配置。

這裏我們分析一下上面的示例代碼:

@Aspect:描述一個切面類,定義切面類的時候需要打上這個註解

@Component:泛指組件,當組件不好歸類的時候,我們可以使用這個註解進行標註。

@PointCut("execution(* com.ding..controller.*.*(..))"):定義切點,括號內的為攔截的路徑,這裏指目錄下的controller中所以方法

這裏定義切點的方法為printLog(),在進行前置通知、後置通知、環繞通知的時候,就可以根據這個方法進行攔截。這裏我們用到了環繞通知的方式: @Around("printLog()"),定義後,在進行controller中方法調用時就會先調用這裏的doAround方法。方法中的含義在註釋中已經寫清楚了,可以打斷點再看每段代碼的具體含義。

後記

本文通過一個案例講解了一下使用切面進行日誌處理的功能,重點在於配置切點、環繞通知、方法調用。這些成功後就按照自己需求進行日誌內容的輸出了。

==================================================================================

輸出倒逼輸入,作為技術人員教是最好的學習方法,我是一名愛思考、愛學習、涉獵廣泛想搞事情的程序員。

堅持就是娛樂,因為驚喜更重要

==================================================================================

controller層統一攔截進行日誌處理