• AOP日志拦截器


    各位读者,大家好!

         我们在开发项目时,要经常输出大量的日志,以便问题的排查。但是写日志又显得特别繁琐,特别是固定的日志内容。

         比如,接口开发时,经常要打印出【入参】、【响应结果】及【异常日志】,那么有没有办法统一管理这些日志呢,答案是可以的。

        下面我们就运用Spring的AOP技术来实现它,我们这里用到了Before(前置通知)、After(后置通知)及Throwable(异常通知)。

       

        思路:要想对不同的方法打印各自的日志,那么就需要开发者提供这个方法的使用说明,在这里我们就自定义一个注解MyLogAdvice,其作用是用于标注需要被日志拦截器管理的方法,及该方法的说明。如下:

     1 package com.cheng2839.annotation;
     2 
     3 import java.lang.annotation.Documented;
     4 import java.lang.annotation.ElementType;
     5 import java.lang.annotation.Retention;
     6 import java.lang.annotation.RetentionPolicy;
     7 import java.lang.annotation.Target;
     8 
     9 /**
    10  * 日志打印
    11  * @author cheng2839
    12  * @date 2018年11月16日
    13  */
    14 @Retention(RetentionPolicy.RUNTIME)
    15 @Target(ElementType.METHOD)
    16 @Documented
    17 public @interface CustomLogAdvice {
    18 
    19     //方法作用
    20     String msg();
    21 
    22 }

        接下来,我们开发日志拦截器LogAdvice

      1 package com.cheng2839.interceptor;
      2 
      3 import com.cheng2839.annotation.MyLogAdvice;
      4 import org.aspectj.lang.JoinPoint;
      5 import org.aspectj.lang.Signature;
      6 import org.aspectj.lang.annotation.AfterReturning;
      7 import org.aspectj.lang.annotation.AfterThrowing;
      8 import org.aspectj.lang.annotation.Aspect;
      9 import org.aspectj.lang.annotation.Before;
     10 import org.aspectj.lang.annotation.Pointcut;
     11 import org.aspectj.lang.reflect.MethodSignature;
     12 import org.slf4j.Logger;
     13 import org.slf4j.LoggerFactory;
     14 import org.springframework.stereotype.Component;
     15 
     16 import java.io.PrintWriter;
     17 import java.io.StringWriter;
     18 import java.lang.reflect.Method;
     19 
     20 /**
     21  * 日志AOP拦截
     22  * @author cheng2839
     23  * @date 2018年11月16日
     24  */
     25 @Aspect
     26 @Component
     27 public class LogAdvice {
     28 
     29     private Logger logger = LoggerFactory.getLogger(this.getClass());
     30 
     31     @Pointcut("execution(@(@com.cheng2839.annotation.MyLogAdvice *) * *(..)) " +
     32             "|| execution(@com.cheng2839.annotation.MyLogAdvice * *(..)) " +
     33             "|| execution(@(@com.cheng2839.annotation.MyLogAdvice *) * *(..))")
     34     public void log() {}
     35 
     36     /**
     37      * 前置 - 入参打印
     38      * @param joinPoint
     39      * @author cheng2839
     40      * @date 2018年11月16日
     41      */
     42     @Before("log()")
     43     public void beforeAspect(JoinPoint joinPoint) {
     44         try {
     45             StringBuilder methodMsg = getMethodMsg(joinPoint);
     46             if (ObjectUtil.isNotNullOrNotEmpty(methodMsg)) {
     47                 Object[] args = joinPoint.getArgs();
     48                 StringBuilder paramToString = new StringBuilder();
     49                 if (args!=null) {
     50                     for (Object p : args) {
     51                         paramToString.append(p);
     52                         paramToString.append(' ');
     53                     }
     54                 }
     55                 logger.info("{}入参:{}", methodMsg.toString(), paramToString.toString());
     56             }
     57         } catch (Exception ex) {
     58             logger.error("LogAdvice.beforeAspect exception:{}", ex);
     59         }
     60 
     61     }
     62 
     63     /**
     64      * 后置通知 - 响应结果打印
     65      * @param joinPoint
     66      * @param result
     67      * @throws Throwable
     68      * @author cheng2839
     69      * @date 2018年11月16日
     70      */
     71     @AfterReturning(pointcut = "log()", returning = "result")
     72     public void afterAspect(JoinPoint joinPoint, Object result) {
     73         try {
     74             StringBuilder methodMsg = getMethodMsg(joinPoint);
     75             if (ObjectUtil.isNotNullOrNotEmpty(methodMsg)) {
     76                 logger.info("{}响应结果:{}", methodMsg.toString(), result);
     77             }
     78         } catch (Exception ex) {
     79             logger.error("LogAdvice.afterAspect exception:{}", ex);
     80         }
     81     }
     82 
     83     /**
     84      * 异常捕获 - 异常打印
     85      * @param joinPoint
     86      * @author cheng2839
     87      * @date 2018年11月16日
     88      */
     89     @AfterThrowing(value = "log()", throwing = "e")
     90     public void throwAspect(JoinPoint joinPoint, Exception e) {
     91         try {
     92             StringBuilder methodMsg = getMethodMsg(joinPoint);
     93             if (ObjectUtil.isNotNullOrNotEmpty(methodMsg)) {
     94                 StringWriter sw = new StringWriter();
     95                 e.printStackTrace(new PrintWriter(sw));
     96                 logger.error("{}异常:{}", methodMsg.toString(), sw.toString());
     97             }
     98         } catch (Exception ex) {
     99             logger.error("LogAdvice.throwAspect exception:{}", ex);
    100         }
    101     }
    102 
    103     /**
    104      * 组装方法提示消息
    105      * @param joinPoint
    106      * @return
    107      * @author cheng2839
    108      * @date 2018年11月16日
    109      */
    110     private StringBuilder getMethodMsg(JoinPoint joinPoint) {
    111         Signature signature = joinPoint.getSignature();
    112         Method method = ((MethodSignature) signature).getMethod();
    113         MyLogAdvice myLogAdvice = method.getAnnotation(MyLogAdvice.class);
    114 
    115         StringBuilder methodMsg = null;
    116         if (myLogAdvice != null) {
    117             methodMsg = new StringBuilder();
    118             methodMsg.append(method.getDeclaringClass().getName()); //class name
    119             methodMsg.append('.');
    120             methodMsg.append(method.getName()); //method name
    121             methodMsg.append(' ');
    122             methodMsg.append('-');
    123             methodMsg.append(' ');
    124             methodMsg.append(myLogAdvice.msg()); //method remark
    125         }
    126         return methodMsg;
    127     }
    128 }

        接下来,我们写个测试接口测试一下:

        注意:这里我创建了一个springBoot服务,端口:8392,服务的创建不再这里赘述。

     1 package com.cheng2839.controller;
     2 
     3 import com.cheng2839.annotation.MyLogAdvice;
     4 import org.springframework.web.bind.annotation.GetMapping;
     5 import org.springframework.web.bind.annotation.RequestMapping;
     6 import org.springframework.web.bind.annotation.RequestParam;
     7 import org.springframework.web.bind.annotation.RestController;
     8 
     9 /**
    10  * 日志拦截器测试类
    11  * @author cheng2839
    12  * @date 2018年11月16日
    13  */
    14 @RestController
    15 @RequestMapping("/test")
    16 public class TestLogAspectController {
    17 
    18     @MyLogAdvice(msg = "测试日志拦截器")
    19     @GetMapping(value = "/testLogAspect")
    20     public String testLogAspect(@RequestParam("name") String param) {
    21         return "hello,spring aop";
    22     }
    23 
    24 }

       在postman或者浏览器地址栏中用GET请求访问:http://127.0.0.1:8392/test/testLogAspect?name=cheng2839

     

        日志输出结果如下:

    1 2018-11-16 17:21:09.130 [http-nio-8392-exec-3] [INFO] com.cheng2839.interceptor.LogAdvice:com.cheng2839.controller.TestLogAspectController.testLogAspect - 测试日志拦截器入参:cheng2839 
    2 2018-11-16 17:21:09.132 [http-nio-8392-exec-3] [INFO] com.cheng2839.interceptor.LogAdvice:com.cheng2839.controller.TestLogAspectController.testLogAspect - 测试日志拦截器响应结果:hello,spring aop

                                          ——此记

    ____________________________特此,勉励____________________________
    本文作者cheng2839
    本文链接https://www.cnblogs.com/cheng2839
    关于博主:评论和私信会在第一时间回复。
    版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
    声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
  • 相关阅读:
    GridView 内部添加控件
    TreeList获取选中内容
    TreeList简介
    TreeList
    DEV—【GridControl 按钮列无法触发点击事件解决方案】
    dev 多行文本 MemoEdit
    DevExpress控件使用小结
    DEV常用设置
    DEV常用设置
    documentManager1注意事项
  • 原文地址:https://www.cnblogs.com/cheng2839/p/12614108.html
Copyright © 2020-2023  润新知