前言
在項目中添加統(tǒng)一日志時,我們往往會用到aop進行切面處理董饰,常用在controller層添加切面奥喻,以處理請求和返回的各項參數(shù)數(shù)據(jù)。
使用切面進行日志處理
下面我們就看一個例子說明基本的使用方式:
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();
// 獲取調(diào)用方法相信
Signature signature = pjp.getSignature();
String className = signature.getDeclaringTypeName();
String methodName = signature.getName();
LOGGER.info("請求開始, {}#{}() URI: {}, method: {}, URL: {}, params: {}", className, methodName, uri, method, url,
queryString);
//result的值就是被攔截方法的返回值
try {
//proceed方法是調(diào)用實際所攔截的controller中的方法侈贷,這里的result為調(diào)用方法后的返回值
Object result = pjp.proceed();
long endTime = System.currentTimeMillis();
//定義請求結束時的返回數(shù)據(jù),包括調(diào)用時間等脂、返回值結果等
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實現(xiàn)俏蛮,我們直接使用此實現(xiàn)即可,本來使用aop還需要定義一些xml文件上遥,但由于我們使用的是spring-boot框架搏屑,這一步就省略掉了。也就是說粉楚,在spring-boot中辣恋,我們可以直接使用aop而不需要任何的配置。
這里我們分析一下上面的示例代碼:
@Aspect:描述一個切面類,定義切面類的時候需要打上這個注解
@Component:泛指組件抑党,當組件不好歸類的時候包警,我們可以使用這個注解進行標注。
@PointCut("execution(* com.ding..controller..(..))"):定義切點底靠,括號內(nèi)的為攔截的路徑害晦,這里指目錄下的controller中所以方法
這里定義切點的方法為printLog(),在進行前置通知暑中、后置通知壹瘟、環(huán)繞通知的時候,就可以根據(jù)這個方法進行攔截鳄逾。這里我們用到了環(huán)繞通知的方式: @Around("printLog()")稻轨,定義后,在進行controller中方法調(diào)用時就會先調(diào)用這里的doAround方法雕凹。方法中的含義在注釋中已經(jīng)寫清楚了殴俱,可以打斷點再看每段代碼的具體含義。
后記
本文通過一個案例講解了一下使用切面進行日志處理的功能枚抵,重點在于配置切點线欲、環(huán)繞通知、方法調(diào)用汽摹。這些成功后就按照自己需求進行日志內(nèi)容的輸出了李丰。
============================================================
輸出倒逼輸入,作為技術人員教是最好的學習方法逼泣,我是一名愛思考趴泌、愛學習、涉獵廣泛想搞事情的程序員拉庶。
堅持就是娛樂嗜憔,因為驚喜更重要
============================================================