• 【工作记录】springboot集成aop实现日志@20230918


    springboot集成aop实现日志

    1. 添加依赖

    
    <dependency>
      <groupId>org.springframework.bootgroupId>
      <artifactId>spring-boot-starter-aopartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2. 定义注解

    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface ActionLog {
    
        String action() default "";
    
        String topic() default "";
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    3. 定义切面类

    import com.cnhqd.authcenter.framework.common.utils.IpUtils;
    import com.cnhqd.authcenter.framework.common.utils.JsonUtils;
    import lombok.extern.slf4j.Slf4j;
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.annotation.*;
    import org.aspectj.lang.reflect.MethodSignature;
    import org.springframework.stereotype.Component;
    import org.springframework.web.context.request.RequestContextHolder;
    import org.springframework.web.context.request.ServletRequestAttributes;
    
    import javax.servlet.http.HttpServletRequest;
    
    @Slf4j
    @Aspect
    @Component
    public class ActionLogAspect {
    
      @Pointcut("@annotation(com.cnhqd.authcenter.framework.common.log.ActionLog)")
      public void actionLog() {
    
      }
    
      /*** 在切点之前织入* @param joinPoint* @throws Throwable*/
      @Before("actionLog()")
      public void doBefore(JoinPoint joinPoint) throws Exception {
        // 开始打印请求日志
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();// 打印请求相关参数
        log.info("=================== Start ====================");
        // 打印请求url
        log.info("URL            : {}", request.getRequestURL().toString());
        // 打印Httpmethod
        log.info("HTTP Method    : {}", request.getMethod());
        // 打印调用 controller 的全路径以及执行方法
        log.info("Class Method   : {}.{}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());
        // 打印请求的IP
        log.info("IP             : {}", IpUtils.getIpAddr(request));
        // 打印请求入参
        log.info("Request Args   : {}", JsonUtils.toJsonString(joinPoint.getArgs()));
        ActionLog annotation = ((MethodSignature) joinPoint.getSignature()).getMethod().getAnnotation(ActionLog.class);
        log.info("topic          :{}", annotation.topic());
        log.info("action         :{}", annotation.action());
      }
    
      @AfterReturning("actionLog()")
      public void afterReturning(){
        log.info("result        :{}", 200);
        log.info("=================== End ====================");
      }
    
      @AfterThrowing(pointcut = "actionLog()", throwing = "ex")
      public void afterThrowing(Throwable ex) {
        log.info("result        :{}", ex.getMessage());
        log.info("=================== End ====================");
      }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    各注解说明:

    @Aspect:声明该类为一个注解类;  
    
    @Pointcut:定义一个切点,后面跟随一个表达式,表达式可以定义为某个 package 下的方法,也可以是自定义注解等;  
    
    @Before: 在切点之前,织入相关代码;  
    
    @After: 在切点之后,织入相关代码;  
    
    @AfterReturning: 在切点返回内容后,织入相关代码,一般用于对返回值做些加工处理的场景;  
    
    @AfterThrowing: 用来处理当织入的代码抛出异常后的逻辑处理;  
    
    @Around: 在切入点前后织入代码,并且可以自由的控制何时执行切点;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    4. 简单测试

    编写测试controller

    import com.cnhqd.authcenter.framework.common.log.ActionLog;
    import com.cnhqd.authcenter.system.vo.SysAccountLoginVO;
    import org.springframework.web.bind.annotation.*;
    
    @RestController
    @RequestMapping("testAops")
    public class TestAopsController {
    
        @GetMapping("get")
        @ActionLog(action = "get", topic = "测试AOP")
        public String get(String id) {
            return id;
        }
    
        @PostMapping("post")
        @ActionLog(action = "post", topic = "测试AOP")
        public String post(@RequestBody SysAccountLoginVO vo) {
            System.out.println(JsonUtils.toJsonString(vo));
            return "success";
        }
    
        @GetMapping("getEx")
        @ActionLog(action = "getEx", topic = "测试AOP")
        public String getEx() {
            throw new RuntimeException("getEx-这里是异常输出测试");
        }
    
        @PostMapping("postEx")
        @ActionLog(action = "postEx", topic = "测试AOP")
        public String postEx() {
            throw new RuntimeException("postEx-这里是异常输出测试");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    使用postman发送对应请求,观察控制台输出
    postman-get
    console-get
    postman-getEx
    console-getEx
    postman-post
    console-post
    postman-postEx
    console-postEx
    可以看到日志可以正常输出,如有必要保存相关数据到数据库即可。

  • 相关阅读:
    性能测试 - 理论
    如何让家居设备快速通过Matter认证?移远通信为您带来标准回答
    高通平台稳定性分析-CFI failure
    cv2.calibrateCamera函数
    两万字长文世界编程语言大串讲
    Leetcode.25 K个一组翻转链表(模拟/递归)
    面试用-常用注解
    verilog练习——组合逻辑
    vue的第2篇 开发环境vscode的安装以及创建项目空间
    MyBatis
  • 原文地址:https://blog.csdn.net/u010361276/article/details/132990085