springboot自定义日志注解@Log

  1. 创建自定义注解接口

    package com.example.lambda.annotation;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    /**
     * @author: WZ
     * @create: 2022-10-17 09:18
     * @description: 1、自定义日志注解接口
     * @Target(ElementType.TYPE) // 接口、类、枚举、注解
     * @Target(ElementType.FIELD) // 字段、枚举的常量
     * @Target(ElementType.METHOD) //方法
     * @Target(ElementType.PARAMETER) //方法参数
     * @Target(ElementType.CONSTRUCTOR) //构造函数
     * @Target(ElementType.LOCAL_VARIABLE)//局部变量
     * @Target(ElementType.ANNOTATION_TYPE)//注解
     * @Target(ElementType.PACKAGE) ///包
     * @Retention注解: 这个参数有三种,一般默认第三种
     * <p>
     * 1. RetentionPolicy.SOURCE —— 这种类型的Annotations只在源代码级别保留,
     * <p>
     * 编译时就会被忽略
     * <p>
     * 2. RetentionPolicy.CLASS —— 这种类型的Annotations编译时被保留,在class文件中存在,
     * <p>
     * 但JVM将会忽略
     * <p>
     * 3. RetentionPolicy.RUNTIME —— 这种类型的Annotations将被JVM保留,
     * <p>
     * 所以他们能在运行时被JVM或其他使用反射机制的代码所读取和使用。
     * 第二种写法:
     * @Documented 和 @Order(优先级:数字越小优先级越高)
     * @Documented 注解表明这个注解应该被 javadoc工具记录. 默认情况下,javadoc是不包括注解的. 但如果声明注解时指定了 @Documented,则它会被 javadoc 之类的工具处理, 所以注解类型信息也会被包括在生成的文档中。
     * @Order标记定义了组件的加载顺序,这个标记包含一个value属性。属性接受整形值。 如:1,2 等等。值越小拥有越高的优先级。
     * <p>
     * Ordered.HIGHEST_PRECEDENCE这个属性值是最高优先级的属性,它的值是-2147483648,对应的最低属性值是Ordered.LOWEST_PRECEDENCE,它的值是2147483647。
     */
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Log {
        /**
         * 模块
         */
        String title() default "";
    
        /**
         * 是否保存请求的参数
         */
        boolean isSaveRequestData() default true;
    
        /**
         * 是否保存响应的参数
         */
        boolean isSaveResponseData() default true;
    }
    
    
  2. 创建LogAspect类对自定义注解进行操作

    package com.example.lambda.annotation;
    
    import com.alibaba.fastjson.JSONObject;
    import lombok.extern.slf4j.Slf4j;
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.Signature;
    import org.aspectj.lang.annotation.AfterReturning;
    import org.aspectj.lang.annotation.AfterThrowing;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Pointcut;
    import org.springframework.stereotype.Component;
    import org.springframework.validation.BindingResult;
    import org.springframework.web.context.request.RequestAttributes;
    import org.springframework.web.context.request.RequestContextHolder;
    import org.springframework.web.context.request.ServletRequestAttributes;
    import org.springframework.web.multipart.MultipartFile;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.util.Collection;
    import java.util.Map;
    
    /**
     * 操作日志记录处理
     *
     * @author: WZ
     * @create: 2022-10-17 09:18
     * @description: 2、自定义注解操作
     */
    @Aspect
    @Component
    @Slf4j
    public class LogAspect {
    
    
        /**
         * 配置织入点
         */
        @Pointcut("@annotation(com.example.lambda.annotation.Log)")
        public void logPointCut() {
        }
    
        /**
         * 处理完请求后执行
         *
         * @param joinPoint 切点
         */
        @AfterReturning(pointcut = "@annotation(controllerLog)", returning = "jsonResult")
        public void doAfterReturning(JoinPoint joinPoint, Log controllerLog, Object jsonResult) {
            handleLog(joinPoint, controllerLog, null, jsonResult);
        }
    
        /**
         * 拦截异常操作
         *
         * @param joinPoint 切点
         * @param e         异常
         */
        @AfterThrowing(value = "@annotation(controllerLog)", throwing = "e")
        public void doAfterThrowing(JoinPoint joinPoint, Log controllerLog, Exception e) {
            handleLog(joinPoint, controllerLog, e, null);
        }
    
        protected void handleLog(final JoinPoint joinPoint, Log controllerLog, final Exception e, Object jsonResult) {
            try {
                //获取封装了署名信息的对象,在该对象中可以获取到目标方法名,所属类的Class等信息
                Signature signature = joinPoint.getSignature();
                //获取传入目标方法的参数对象
                Object[] args = joinPoint.getArgs();
                //获取被代理的对象
                Object target = joinPoint.getTarget();
                //获取代理的对象
                Object aThis = joinPoint.getThis();
                //接口请求方式
                String method = getHttpMethod();
    
                String params = argsArrayToString(joinPoint.getArgs());
                /**
                 * 是否保存请求的参数
                 */
                if (controllerLog.isSaveRequestData()) {
    
                }
                /**
                 * 是否保存响应的参数
                 */
                if (controllerLog.isSaveResponseData()) {
    
                }
    
                log.info("---------------------signature:{}", signature);
                log.info("---------------------params:{}", params);
                log.info("---------------------target:{}", target);
                log.info("---------------------aThis:{}", aThis);
                log.info("---------------------method:{}", method);
                log.info("---------------------异常信息:{}", e);
                log.info("---------------------jsonResult:{}", jsonResult);
    
            } catch (Exception exp) {
                // 记录本地异常日志
                log.error("==前置通知异常==");
                log.error("异常信息:{}", exp.getMessage());
                exp.printStackTrace();
            }
        }
    
        /**
         * 获取请求方式
         *
         * @return
         */
        public static ServletRequestAttributes getAttributes() {
            RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
            return (ServletRequestAttributes) attributes;
        }
    
        public static String getHttpMethod() {
            String method = getAttributes().getRequest().getMethod();
            return method;
        }
    
        /**
         * 参数拼装
         */
        private String argsArrayToString(Object[] paramsArray) {
            String params = "";
            if (paramsArray != null && paramsArray.length > 0) {
                for (Object o : paramsArray) {
                    if (o != null && !isFilterObject(o)) {
                        try {
                            Object jsonObj = JSONObject.toJSONString(o);
                            params += jsonObj.toString() + " ";
                        } catch (Exception e) {
                        }
                    }
                }
            }
            return params.trim();
        }
    
        /**
         * 判断是否需要过滤的对象。
         *
         * @param o 对象信息。
         * @return 如果是需要过滤的对象,则返回true;否则返回false。
         */
        @SuppressWarnings("rawtypes")
        public boolean isFilterObject(final Object o) {
            Class<?> clazz = o.getClass();
            if (clazz.isArray()) {
                return clazz.getComponentType().isAssignableFrom(MultipartFile.class);
            } else if (Collection.class.isAssignableFrom(clazz)) {
                Collection collection = (Collection) o;
                for (Object value : collection) {
                    return value instanceof MultipartFile;
                }
            } else if (Map.class.isAssignableFrom(clazz)) {
                Map map = (Map) o;
                for (Object value : map.entrySet()) {
                    Map.Entry entry = (Map.Entry) value;
                    return entry.getValue() instanceof MultipartFile;
                }
            }
            return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse
                || o instanceof BindingResult;
        }
    }
    
    
  3. 使用自定义注解@Log

    	@PostMapping("test2")
        @Log(title = "测试自定义日志post")
        public Object test1(@RequestBody Map map) {
            return new HashMap<String,Object>(){
                {
                    put("name", "张三");
                    put("age", 18);
                    put("sex", "男");
                }
            };
        }
    
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值