天天看點

AOP實作日志記錄

作者:IT技術控

需求分析

需要通過日志記錄接口調用資訊。便于後期調試排查。并且可能有很多接口都需要進行日志的記錄。

接口被調用時日志列印格式如下:

c複制代碼        log.info("=======Start=======");
        // 列印請求 URL
        log.info("URL            : {}",);
        // 列印描述資訊
        log.info("BusinessName   : {}", );
        // 列印 Http method
        log.info("HTTP Method    : {}", );
        // 列印調用 controller 的全路徑以及執行方法
        log.info("Class Method   : {}.{}", );
        // 列印請求的 IP
        log.info("IP             : {}",);
        // 列印請求入參
        log.info("Request Args   : {}",);
        // 列印出參
        log.info("Response       : {}", );
        // 結束後換行
        log.info("=======End=======" + System.lineSeparator());
           

思路分析

相當于是對原有的功能進行增強。并且是批量的增強,這個時候就非常适合用AOP來進行實作,例如對更新使用者的接口進行日志記錄,當使用者調用這個接口的時候,對調用的資訊進行記錄

less複制代碼    @PutMapping("/userInfo")
    public ResponseResult updateUserInfo(@RequestBody User user){
        return userService.updateUserInfo(user);
    }
           

代碼實作

定義自定義注解@SystemLog

建立接口

在annotation包下建立SystemLog

@Retention(RetentionPolicy.RUNTIME)表示在運作是生效

@Target(ElementType.METHOD)作用類型是方法

less複制代碼@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface SystemLog {
    String businessName();
}
           

定義切面類LogAspect

@Pointcut注解,它主要定義切入點,用來标記一個方法以及在何處觸發斷點。它可以定義切入點表達式,标記一個方法,以及指定何時執行某個動作。

@Around注解可以用來在調用一個具體方法前和調用後來完成一些具體的任務。比如在在調用pt()方法前調用printLog()方法。

less複制代碼@Aspect //該注解聲明這個類為一個切面類
@Component
@Slf4j
public class LogAspect {

    @Pointcut("@annotation(com.whj.annotation.SystemLog)")
    public void pt() {
    }

    @Around("pt()")
    public Object printLog(ProceedingJoinPoint joinPoint) throws Throwable{

        Object ret;
        try {
            handleBefore(joinPoint);
            // 傳回執行的結果
            ret = joinPoint.proceed();
            handleAfter(ret);
        } finally {
            // 結束後換行
            log.info("=======End=======" + System.lineSeparator());
        }
        return ret;
    }

    private void handleAfter(Object ret) {
        // 列印出參
        log.info("Response       : {}", JSON.toJSON(ret));
    }

    private void handleBefore(ProceedingJoinPoint joinPoint) {

        // 向下轉行  擷取被增強方法的URL
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();

        //擷取被增強方法的注解對象
        SystemLog systemLog = getSystemLog(joinPoint);

        log.info("=======Start=======");
        // 列印請求 URL
        log.info("URL            : {}",request.getRequestURL());
        // 列印描述資訊
        log.info("BusinessName   : {}", systemLog.businessName());
        // 列印 Http method
        log.info("HTTP Method    : {}", request.getMethod());
        // 列印調用 controller 的全路徑以及執行方法
        log.info("Class Method   : {}.{}", joinPoint.getSignature().getDeclaringTypeName(),joinPoint.getSignature().getName());
        // 列印請求的 IP
        log.info("IP             : {}",request.getRemoteHost());
        // 列印請求入參
        log.info("Request Args   : {}", JSON.toJSON(joinPoint.getArgs()));
    }

    private SystemLog getSystemLog(ProceedingJoinPoint joinPoint) {

        //将增強方法的整體作為一個對象封裝成methodSignature
        MethodSignature methodSignature = (MethodSignature)joinPoint.getSignature();
        // 擷取方法上的注解
        SystemLog systemLog = methodSignature.getMethod().getAnnotation(SystemLog.class);
        return systemLog;
    }
}
           

在需要記錄日志的方法加上注解

less複制代碼    @PutMapping("/userInfo")
    @SystemLog(businessName="更新使用者資訊")
    public ResponseResult updateUserInfo(@RequestBody User user){
        return userService.updateUserInfo(user);
    }
           

運作結果

AOP實作日志記錄

作者:專注學習

連結:https://juejin.cn/post/7237520441554993207

繼續閱讀