Spring Boot 使用 AOP 記錄日志
本文轉(zhuǎn)載自微信公眾號「武培軒」,作者武培軒 。轉(zhuǎn)載本文請聯(lián)系武培軒公眾號。
在項目開發(fā)中經(jīng)常,日志系統(tǒng)是必不可少的,特別是管理系統(tǒng),對于重要的操作都會有操作日志,然而這個操作不需要我們在相應的方法中一個一個的去實現(xiàn),這肯定是不合適的,這樣的操作無疑是加大了開發(fā)量,而且不易維護,所以實際項目中總是利用AOP(Aspect Oriented Programming)即面向切面編程來記錄系統(tǒng)中的操作日志。
下面就來介紹如何在 Spring Boot 中 使用 AOP 記錄日志:
加入依賴
首先加入 AOP 依賴:
- <dependency>
 - <groupId>org.springframework.boot</groupId>
 - <artifactId>spring-boot-starter-aop</artifactId>
 - </dependency>
 
創(chuàng)建日志注解類
創(chuàng)建一個日志注解類,這樣就可以在需要記錄日志的方法上加上注解就可以記錄日志了,注解內(nèi)容如下:
- @Target({ElementType.PARAMETER, ElementType.METHOD})
 - @Retention(RetentionPolicy.RUNTIME)
 - @Documented
 - public @interface AopLogger {
 - String describe() default "";
 - }
 
配置 AOP 切面
定義一個 AopLoggerAspect 切面類,用 @Aspect 聲明該類為切面類。
- @Component
 - public class AopLoggerAspect {
 - private final Logger logger = LoggerFactory.getLogger(this.getClass());
 - @Pointcut("@annotation(com.wupx.aop.logger.annotation.AopLogger)")
 - public void aopLoggerAspect() {
 - }
 - /**
 - * 環(huán)繞觸發(fā)
 - *
 - * @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 = "-";
 - }
 - // 打印請求相關參數(shù)
 - 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());
 - // 打印調(diào)用 controller 的全路徑以及執(zhí)行方法
 - logger.info("Class Method : {}.{}", point.getSignature().getDeclaringTypeName(), point.getSignature().getName());
 - // 打印請求的 IP
 - logger.info("IP : {}", request.getRemoteAddr());
 - // 打印請求入?yún)?nbsp;
 - 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」 為在切入點前后織入代碼,并且可以自由的控制何時執(zhí)行切點。
測試
接下來編寫 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 接口,輸出的日志如下所示:
可以看到把入?yún)?、出參以及接口信息都記錄了下來,是不是很簡單呢,只需要簡單幾步就可以實現(xiàn) AOP 日志,大家可以自己實踐下。
本文的完整代碼在 https://github.com/wupeixuan/SpringBoot-Learn 的 aop-logger 目錄下。
















 
 
 













 
 
 
 