Spring Boot 使用 AOP 記錄日誌


在項目開發中經常,日誌系統是必不可少的,特別是管理系統,對於重要的操作都會有操作日誌,然而這個操作不需要我們在相應的方法中一個一個的去實現,這肯定是不合適的,這樣的操作無疑是加大了開發量,而且不易維護,所以實際項目中總是利用AOP(Aspect Oriented Programming)即面向切面編程來記錄系統中的操作日誌。

下面就來介紹如何在 Spring Boot 中 使用 AOP 記錄日誌:

加入依賴

首先加入 AOP 依賴:

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

創建日誌註解類

創建一個日誌註解類,這樣就可以在需要記錄日誌的方法上加上註解就可以記錄日誌了,註解內容如下:

@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AopLogger {

    String describe() default "";
}

配置 AOP 切面

定義一個 AopLoggerAspect 切面類,用 @Aspect 聲明該類爲切面類。

@Aspect
@Component
public class AopLoggerAspect {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Pointcut("@annotation(com.wupx.aop.logger.annotation.AopLogger)")
    public void aopLoggerAspect() {
    }

    /**
     * 環繞觸發
     *
     * @param point
     * @return
     */
    @Around("aopLoggerAspect()")
    public Object doAround(ProceedingJoinPoint point) {
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) requestAttributes;
        HttpServletRequest request = servletRequestAttributes.getRequest();
        Object result = null;
        long startTime = System.currentTimeMillis();
        try {
            result = point.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
            logger.error(throwable.getMessage());
        }
        String describe = getAopLoggerDescribe(point);
        if (StringUtils.isBlank(describe)) {
            describe = "-";
        }
        // 打印請求相關參數
        logger.info("========================================== Start ==========================================");
        logger.info("Describe       : {}", describe);
        // 打印請求 url
        logger.info("URL            : {}", request.getRequestURL());
        logger.info("URI            : {}", request.getRequestURI());
        // 打印 Http method
        logger.info("HTTP Method    : {}", request.getMethod());
        // 打印調用 controller 的全路徑以及執行方法
        logger.info("Class Method   : {}.{}", point.getSignature().getDeclaringTypeName(), point.getSignature().getName());
        // 打印請求的 IP
        logger.info("IP             : {}", request.getRemoteAddr());
        // 打印請求入參
        logger.info("Request Args   : {}", point.getArgs());
        // 打印請求出參
        logger.info("Response Args  : {}", result);
        logger.info("Time Consuming : {} ms", System.currentTimeMillis() - startTime);
        logger.info("=========================================== End ===========================================");
        return result;
    }

    /**
     * 獲取註解中對方法的描述信息
     *
     * @param joinPoint 切點
     * @return describe
     */
    public static String getAopLoggerDescribe(JoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        AopLogger controllerLog = method.getAnnotation(AopLogger.class);
        return controllerLog.describe();
    }
}

其中 「@Pointcut」 是定義一個切點,後面跟隨一個表達式,表達式可以定義爲某個 package 下的方法,也可以是自定義註解等。

「@Around」 爲在切入點前後織入代碼,並且可以自由的控制何時執行切點。

測試

接下來編寫 Controller 層來進行測試:

@RestController
@RequestMapping("/user")
public class UserController {

    private final UserService userService;

    public UserController(UserService userService) {
        this.userService = userService;
    }

    @PostMapping
    @AopLogger(describe = "添加用戶")
    public String addUser(@RequestBody User user) {
        UserEntity userEntity = new UserEntity();
        BeanUtils.copyProperties(user, userEntity);
        return userService.addUser(userEntity);
    }
}

只需要在接口上填寫 @AopLogger 就可以記錄操作日誌。

啓動服務,通過 PostMan 請求 http://localhost:8080/user 接口,輸出的日誌如下所示:

可以看到把入參、出參以及接口信息都記錄了下來,是不是很簡單呢,只需要簡單幾步就可以實現 AOP 日誌,大家可以自己實踐下。

本文的完整代碼在 https://github.com/wupeixuan/SpringBoot-Learnaop-logger 目錄下。

本文分享自微信公衆號 - 武培軒(wupeixuan404)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章