2021-02-24

1 篇文章 0 订阅
1 篇文章 0 订阅

最近公司项目,日志采用aop切面进行管理,根据业务定制级别,例:定了信息类的日志,错误日志,监控日志,输出不同的日志信息,并yml文件中有一个开关按钮

下面是我的具体实现:

首先 application.yml 如下

server:
  port: 8080
spring:
  application:
    name: aop-logs
    isEnable: false

自定义注解

package com.cjs.example.annotation;

import java.lang.annotation.*;
/***
 * 监控日志
 * **/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface MonitorLog {
    String description() default "";

    boolean async() default false;

}

然后切面处理

package com.cjs.example.aspect;

import com.cjs.example.annotation.MonitorLog;
import com.cjs.example.service.LogOutput;
import com.cjs.example.util.JsonUtil;
import com.cjs.example.util.ThreadUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

@Aspect
@Component
public class MonitorLogAspect {

    private static final Logger LOG = LoggerFactory.getLogger(MonitorLogAspect.class);

    @Value("${spring.application.isEnable}")
    private boolean isEnable;

    @Pointcut("@annotation(com.cjs.example.annotation.MonitorLog)")
    public void pointcutMonitor() {


    }


    @Around("pointcutMonitor()")
    public Object doInvoke(ProceedingJoinPoint pjp) {
        LOG.info("--------------进入monitor日志打印-------------------");
        LOG.info("isEnable:{}",isEnable);
        if(!isEnable){
            return null;
        }

        Object result = null;
        long start = System.currentTimeMillis();

        try {
            result = pjp.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
            LOG.error(throwable.getMessage(), throwable);
            throw new RuntimeException(throwable);
        } finally {
            long end = System.currentTimeMillis();
            long elapsedTime = end - start;

            printLog(pjp, result, elapsedTime);

        }

        return result;
    }
    /**
     * 打印日志
     * @param pjp   连接点
     * @param result    方法调用返回结果
     * @param elapsedTime   方法调用花费时间
     */
    private void printLog(ProceedingJoinPoint pjp, Object result, long elapsedTime) {
        LogOutput strategy = getFocus(pjp);

        if (null != strategy) {
            strategy.setThreadId(ThreadUtil.getThreadId());
            strategy.setResult(JsonUtil.toJSONString(result));
            strategy.setElapsedTime(elapsedTime);
            if (strategy.isAsync()) {
                new Thread(()->LOG.info(strategy.format(), strategy.args())).start();
            }else {
                LOG.info(strategy.format(), strategy.args());
            }
        }
    }

    /**
     * 获取注解
     */
    private LogOutput getFocus(ProceedingJoinPoint pjp) {
        Signature signature = pjp.getSignature();
        String className = signature.getDeclaringTypeName();
        String methodName = signature.getName();
        Object[] args = pjp.getArgs();
        String targetClassName = pjp.getTarget().getClass().getName();
        try {
            Class<?> clazz = Class.forName(targetClassName);
            Method[] methods = clazz.getMethods();
            for (Method method : methods) {
                if (methodName.equals(method.getName())) {
                    if (args.length == method.getParameterCount()) {

                        LogOutput strategy = new LogOutput();
                        strategy.setClassName(className);
                        strategy.setMethodName(methodName);

                        MonitorLog ifoLog = method.getAnnotation(MonitorLog.class);
                        if (null != ifoLog) {
                            strategy.setArguments(JsonUtil.toJSONString(args));
                            strategy.setDescription(ifoLog.description());
                            strategy.setAsync(ifoLog.async());
                            return strategy;
                        }

                        return null;
                    }
                }
            }
        } catch (ClassNotFoundException e) {
            LOG.error(e.getMessage(), e);
        }
        return null;
    }

}

日志输出实体类

package com.cjs.example.service;

import lombok.Data;

import java.io.Serializable;

@Data
public class LogOutput implements Serializable {

    private boolean async;

    private String threadId;

    private String description;

    private String className;

    private String methodName;

    private String arguments;

    private String result;

    private Long elapsedTime;


    public String format() {
        return "线程ID: {},方法描述: {}, 目标类名: {}, 目标方法: {}, 调用参数: {}, 返回结果: {}, 花费时间: {}";
    }

    public Object[] args() {
        return new Object[]{this.threadId, this.description, this.className, this.methodName, this.arguments, this.result, this.elapsedTime};
    }

}

工具包

package com.cjs.example.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;

public class JsonUtil {

    public static String toJSONString(Object object) {
        return JSON.toJSONString(object, SerializerFeature.DisableCircularReferenceDetect);
    }

}

工具包

package com.cjs.example.util;

import java.util.UUID;

public class ThreadUtil {

    private static final ThreadLocal<String> threadLocal = new ThreadLocal<>();

    public static String getThreadId() {
        String threadId = threadLocal.get();
        if (null == threadId) {
            threadId = UUID.randomUUID().toString();
            threadLocal.set(threadId);
        }
        return threadId;
    }

}

写个controller测试

package com.cjs.example.controller.member;

import com.cjs.example.annotation.MonitorLog;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MonitorLogController {
    @GetMapping("/test2")
    @MonitorLog(description = "监控日志信息")
    public String test2(@RequestParam("param") String param, @RequestParam("param1") String param1) {
        return param+":error日志测试";
    }
}

然后启动类启动,进行访问接口就行了,这是走监控日志的,其它定义级别的日志,可以另外再自定义新的注解

原创文章,如需转载请注明链接 https://blog.csdn.net/u014734630/article/details/114013990

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值