1、前言
AOP切面技術,大家應該都聽知道,Spring框架的主要功能之一。
AOP切面的用途很廣,其中一個常見的用途就是列印介面方法的執行日誌和執行時間。
日誌對於一個專案很是重要,不僅有助於調錯,還是後期大資料分析的重要資料來源,這裡我就簡單介紹一下如何在SpringBoot中利用AOP切面列印後端介面的執行情況。
2、切面程式碼
實現方式很簡單,在SpringBoot工程中,增加切面類,程式碼如下:
import cn.zhuifengren.util.JsonUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
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; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; @Aspect
@Component
@Order(Integer.MIN_VALUE)
public class MyAspect { public static final Logger log =
LoggerFactory.getLogger(MyAspect.class); @Around("execution(* cn.zhuifengren.controller..*Controller.*(..))")
public Object recordTimeLog(ProceedingJoinPoint joinPoint) throws Throwable { // 記錄開始時間
long begin = System.currentTimeMillis(); log.info("類資訊:{}", joinPoint.getTarget().getClass());
log.info("方法名:{}", joinPoint.getSignature().getName()); // 獲得request物件
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes sra = (ServletRequestAttributes) requestAttributes;
HttpServletRequest req = sra.getRequest();
log.info("請求地址: {}",req.getRequestURI());
log.info("請求裝置: {}", req.getHeader("user-agent")); // 獲得引數
Object[] args = joinPoint.getArgs();
if (args!=null && args.length>0){
for (int i = 0; i < args.length; i++) {
if (args[i] instanceof HttpServletRequest || args[i] instanceof HttpServletResponse)
continue;
log.info("引數:" + ( args[i]==null? "": JsonUtils.objectToJson(args[i])));
}
} // 執行目標 service
Object result = joinPoint.proceed();
log.info("響應:" + JsonUtils.objectToJson(result)); // 記錄結束時間
long end = System.currentTimeMillis();
long time = end - begin; log.info("執行時間:{} 毫秒", time); return result;
} }
3、程式碼說明
1)@Aspect 和 @Component 兩個註解是切面類必須的,用於標識這是個切面類。
2)@Order(Integer.MIN_VALUE) 註解用於設定切面的執行順序,值越小,切面越早被執行。
3)@Around("execution(* cn.zhuifengren.controller..*Controller.*(..))")
眾所周知,AOP切面的通知方式有5種,方法執行前通知、方法正常執行後通知、環繞通知、方法執行異常通知、最終通知。
這裡的 @Around 就是環繞通知,也就是方法執行前後都會通知。
execution(* cn.zhuifengren.controller..*Controller.*(..)) 是切面表示式,用於指定哪些方法會被通知。
第一個 * 代表方法返回型別 *代表所有型別;
包名代表aop監控的類所在的包;
.. 代表該包以及其子包下的所有類方法;
*Controller 代表類名,代表所有以Controller結尾的類,如果包括所有類,則直接寫 * ;
*(..) 中 *代表類中的方法名,(..)表示方法中的任何引數。
4)ProceedingJoinPoint joinPoint, 此物件是切面方法的引數,從中可以得到方法的請求引數,也用於執行方法得到響應值。
5)joinPoint.getArgs() 獲得引數。
6)Object result = joinPoint.proceed(),執行方法,並得到返回值
4、日誌效果