<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Spring Boot 使用 AOP 記錄日志

          共 7499字,需瀏覽 15分鐘

           ·

          2021-03-04 09:13


          在項(xiàng)目開(kāi)發(fā)中經(jīng)常,日志系統(tǒng)是必不可少的,特別是管理系統(tǒng),對(duì)于重要的操作都會(huì)有操作日志,然而這個(gè)操作不需要我們?cè)谙鄳?yīng)的方法中一個(gè)一個(gè)的去實(shí)現(xiàn),這肯定是不合適的,這樣的操作無(wú)疑是加大了開(kāi)發(fā)量,而且不易維護(hù),所以實(shí)際項(xiàng)目中總是利用AOP(Aspect Oriented Programming)即面向切面編程來(lái)記錄系統(tǒng)中的操作日志。

          下面就來(lái)介紹如何在 Spring Boot 中 使用 AOP 記錄日志:

          加入依賴(lài)

          首先加入 AOP 依賴(lài):

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

          創(chuàng)建日志注解類(lèi)

          創(chuàng)建一個(gè)日志注解類(lèi),這樣就可以在需要記錄日志的方法上加上注解就可以記錄日志了,注解內(nèi)容如下:

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

              String describe() default "";
          }

          配置 AOP 切面

          定義一個(gè) AopLoggerAspect 切面類(lèi),用 @Aspect 聲明該類(lèi)為切面類(lèi)。

          @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 = "-";
                  }
                  // 打印請(qǐng)求相關(guān)參數(shù)
                  logger.info("========================================== Start ==========================================");
                  logger.info("Describe       : {}", describe);
                  // 打印請(qǐng)求 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());
                  // 打印請(qǐng)求的 IP
                  logger.info("IP             : {}", request.getRemoteAddr());
                  // 打印請(qǐng)求入?yún)?br>        logger.info("Request Args   : {}", point.getArgs());
                  // 打印請(qǐng)求出參
                  logger.info("Response Args  : {}", result);
                  logger.info("Time Consuming : {} ms", System.currentTimeMillis() - startTime);
                  logger.info("=========================================== End ===========================================");
                  return result;
              }

              /**
               * 獲取注解中對(duì)方法的描述信息
               *
               * @param joinPoint 切點(diǎn)
               * @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」 是定義一個(gè)切點(diǎn),后面跟隨一個(gè)表達(dá)式,表達(dá)式可以定義為某個(gè) package 下的方法,也可以是自定義注解等。

          「@Around」 為在切入點(diǎn)前后織入代碼,并且可以自由的控制何時(shí)執(zhí)行切點(diǎn)。

          測(cè)試

          接下來(lái)編寫(xiě) Controller 層來(lái)進(jìn)行測(cè)試:

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

              private final UserService userService;

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

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

          只需要在接口上填寫(xiě) @AopLogger 就可以記錄操作日志。

          啟動(dòng)服務(wù),通過(guò) PostMan 請(qǐng)求 http://localhost:8080/user 接口,輸出的日志如下所示:

          可以看到把入?yún)?、出參以及接口信息都記錄了下?lái),是不是很簡(jiǎn)單呢,只需要簡(jiǎn)單幾步就可以實(shí)現(xiàn) AOP 日志,大家可以自己實(shí)踐下。

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

          瀏覽 74
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  波多野成人无码精品视频 | 撸一撸日一日 | 一级片无码| 欧美A欧美A | 日韩视频二区,三区四区五区 |