首页 > 其他分享 >SpringBoot使用自定义日志注解,配置切面

SpringBoot使用自定义日志注解,配置切面

时间:2023-06-14 19:58:23浏览次数:41  
标签:info SpringBoot 自定义 joinPoint 切面 org import logger 注解

1. 使用技巧

以下是需要注意的部分:

  1. 在环绕通知中使用ProceedingJoinPoint,控制目标方法的运行。
  2. 在其他通知类型中使用JoinPoint
  3. 如果使用JoinPoint 则必须位于参数的第一位。
  4. ProceedingJoinPoint 中有特殊的方法proceed()。
  5. 当有多个切面时,使用@Order(11)来指定注解的优先级。
    1. 在切点之前,@Order 从小到大被执行,也就是说越小的优先级越高;
    2. 在切点之后,@Order 从大到小被执行,也就是说越大的优先级越高;
  6. 切面流程:环绕前置--> 普通前置--> 目标方法执行--> 普通返回 --> 普通后置--> 环绕返回 -->环绕后置

2. 使用流程

  1. 在pom中引入相关依赖。

    <properties>
        <fastjson.version>1.2.83</fastjson.version>
    </properties>
    <!--aop依赖-->
    <dependency>
    	<groupId>org.springframework.boot</groupId>
    	<artifactId>spring-boot-starter-aop</artifactId>
    </dependency>
    <!--用于日志切面,以json打印出入参数-->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>${fastjson.version}</version>
    </dependency>
    
  2. 在annotation包下创建WebLog注解。

    package com.zhao.common.annotation;
    
    import java.lang.annotation.*;
    
    /**
     * 配置系统日志
     */
    @Target({ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface WebLog {
        /**
         * 日志描述信息
         */
        String description() default "";
    }
    
  3. 在aspect包下创建WebLogAspect类。

    package com.zhao.common.aspect;
    
    import com.google.gson.Gson;
    import com.zhao.common.annotation.WebLog;
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.*;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.context.annotation.Profile;
    import org.springframework.stereotype.Component;
    import org.springframework.web.context.request.RequestContextHolder;
    import org.springframework.web.context.request.ServletRequestAttributes;
    
    import javax.servlet.http.HttpServletRequest;
    import java.lang.reflect.Method;
    
    /**
     * 系统日志,切面处理类
     */
    @Aspect // 声明该类是一个注解类
    @Component // 注册为组件
    @Profile({"dev", "test"}) // 使用场景:在配置文件中配置
    public class WebLogAspect {
        /**
         * 使用slf4j注解
         */
        private static final Logger logger = LoggerFactory.getLogger(WebLogAspect.class);
        /**
         * 换行符
         */
        private static final String LINE_SEPARATOR = System.lineSeparator();
    
        /**
         * 以自定义的日志注解作为切入点
         */
        @Pointcut("@annotation(com.zhao.annotation.WebLog)")
        public void logPointCut() {
    
        }
    
        /**
         * 在切入点前
         */
        @Before("logPointCut()")
        public void doBefore(JoinPoint joinPoint) throws Throwable {
            // 开始打印日志请求
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = attributes.getRequest();
            // 获取@WebLog注解的描述信息
            String methodDescription = getAspectLogDescription(joinPoint);
            // 打印请求 url
            logger.info("URL            : {}", request.getRequestURL().toString());
            // 打印描述信息
            logger.info("Description    : {}", methodDescription);
            // 打印 Http method
            logger.info("HTTP Method    : {}", request.getMethod());
            // 打印调用 controller 的全路径以及执行方法
            logger.info("Class Method   : {}.{}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());
            // 打印请求的 IP
            logger.info("IP             : {}", request.getRemoteAddr());
            // 打印请求入参
            logger.info("Request Args   : {}", JSON.toJSON(joinPoint.getArgs()));
        }
    
        /**
         * 在切点之后织入
         */
        //@After("logPointCut()")
        //public void doAfter() throws Throwable {
        //    // 接口结束后换行,方便分割查看
        //}
    
        /**
         * 环绕
         */
        @Around("logPointCut()")
        public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
            logger.info("========================================== Start ==========================================");
            long startTime = System.currentTimeMillis();
            Object result = proceedingJoinPoint.proceed();
            // 打印出参
            logger.info("Response Args  : {}", JSON.toJSON(result));
            // 执行耗时
            logger.info("Time-Consuming : {} ms", System.currentTimeMillis() - startTime);
            // 接口结束后换行,方便分割查看
            logger.info("=========================================== End ===========================================" + LINE_SEPARATOR);
            return result;
        }
    
    
        /**
         * 获取切面注解的详细描述
         */
        public String getAspectLogDescription(JoinPoint joinPoint) throws Throwable {
            String targetName = joinPoint.getTarget().getClass().getName();
            String methodName = joinPoint.getSignature().getName();
            Object[] arguments = joinPoint.getArgs();
            Class targetClass = Class.forName(targetName);
            Method[] methods = targetClass.getMethods();
            StringBuilder description = new StringBuilder();
            for (Method method : methods) {
                if (method.getName().equals(methodName)) {
                    Class[] clazzs = method.getParameterTypes();
                    if (clazzs.length == arguments.length) {
                        description.append(method.getAnnotation(WebLog.class).description());
                        break;
                    }
                }
            }
            return description.toString();
        }
    
    }
    
  4. 在application配置文件中设置环境

    Spring:
      profiles:
        active: dev
    
  5. 使用时在方法上添加注解即可。

标签:info,SpringBoot,自定义,joinPoint,切面,org,import,logger,注解
From: https://www.cnblogs.com/zhaohaodong/p/17481213.html

相关文章

  • 根据不同场景(是否需要连接数据库)启动SpringBoot
    1.场景描述描述:使用场景:项目中的一部分业务不需要进行数据库操作,当只使用这部分功能时,希望程序启动时可以不进行数据库的连接项目中需要数据库相关的业务时再进行配置注意:Springboot在启动时会根据pom.xml启动器来判断是否开启相应的自动配置解决方式:设置一个包......
  • 【SpringBoot】注解
    Controller-@RestController-@RequestMapping("/path")Controller内方法@GetMapping("/path/{xxx}")@PostMapping("/path")POST处理函数参数@RequestBody//将Json体参数值按照参数名传入类内对应字段中GET处理函数参数@PathVariable//按名称获取请求路径中的变......
  • 【React工作记录一百零五】springBoot+vue实现登录操作和JWT验证
    前言大家好我是歌谣今天继续进行前后端的一个学习目前进入的是javaweb部分今天来聊聊登录部分和JWT验证部分的书写用户登录loginControllerpackagecom.itheima.controller;importcom.itheima.pojo.Emp;importcom.itheima.pojo.Result;importcom.itheima.service.EmpSer......
  • IDEA 退出 springboot 应用没有关闭
    使用idea发现的问题。当运行spring-boot:run启动项目后,在控制台关闭项目。再次启动项目,报错端口被占用  Addressalreadyinuse:bind。后发现虽然使用idea控制台关闭项目,但是实际上该项目依旧在运行中,只能通过kill进程id来解决。但是这种方式极不方便,总不能每次都......
  • 自定义配置文件
       ......
  • 基于SpringBoot+MyBatis+Thymeleaf的学生管理系统搭建
    学生管理系统Maven工程搭建【步骤】:打开IDEA工具,选择创建一个新工程。选择SpringInitializr,点击Next按钮。大家也可以通过Spring提供的在线创建的方式创建工程,访问(https://start.spring.io),然后将创建后的工程代码zip包解压后,使用IDEA导入工程。这种方式不在本文描述......
  • SpringBoot启动类@SpringBootApplication注解
    在springBoot的启动类中,提供了一个mai函数的程序入口,来启动加载SpringBoot程序,那么注解@SpringBootApplication,通过源码可以看到,它相当于@ComponentScan+@EnableAutoConfiguration+@SpringBootConfiguration。通过@SpringBootConfiguration注解的源码得知,其配置了一个@Confi......
  • iOS-自定义的画圆或弧的UIView
     iOS-自定义的画圆或弧的UIView CustomViewOfCircle.h#import<UIKit/UIKit.h>@interfaceCustomViewOfCircle:UIView{//是否自定义属性:myDotBOOLisDefinedMyDot;//是否自定义属性:myRadiusBOOLisDefinedMyRadius;//是否自定义属......
  • SpringBoot自定义线程池
    SpringBoot自定义线程池在SpringBoot中,可以使用@Configuration和@Bean去设置线程池,用@Value去做线程池的参数配置。线程池配置:importcom.google.common.util.concurrent.ThreadFactoryBuilder;importorg.springframework.beans.factory.annotation.Value;importor......
  • 【vue】前端下载文件自定义文件名称
    【vue】前端下载文件自定义文件名称https://blog.csdn.net/weixin_48200589/article/details/125067618下载文件自定义文件名称文件下载名称不想和后端提供的URL一样怎么办呢?1.首先给按钮去绑定一个事件2.正常我们的下载处理方式3.自定义下载的文件名字文件下载名称......